diff --git a/MyExperiences copy/MyExperiences.xcodeproj/project.pbxproj b/MyExperiences copy/MyExperiences.xcodeproj/project.pbxproj new file mode 100644 index 00000000..6a0365a7 --- /dev/null +++ b/MyExperiences copy/MyExperiences.xcodeproj/project.pbxproj @@ -0,0 +1,523 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 5020E59724B2F63900E70522 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5020E59624B2F63900E70522 /* AppDelegate.swift */; }; + 5020E59924B2F63900E70522 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5020E59824B2F63900E70522 /* SceneDelegate.swift */; }; + 5020E59E24B2F63900E70522 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5020E59C24B2F63900E70522 /* Main.storyboard */; }; + 5020E5A024B2F63A00E70522 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5020E59F24B2F63A00E70522 /* Assets.xcassets */; }; + 5020E5A324B2F63A00E70522 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5020E5A124B2F63A00E70522 /* LaunchScreen.storyboard */; }; + 5020E5AB24B2F8B000E70522 /* CreateANewExperienceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5020E5AA24B2F8B000E70522 /* CreateANewExperienceViewController.swift */; }; + 5020E5AD24B2FBC300E70522 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5020E5AC24B2FBC300E70522 /* GoogleService-Info.plist */; }; + 5053D08424B8D40700EA1276 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08324B8D40700EA1276 /* Post.swift */; }; + 5053D08624B8D4A200EA1276 /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08524B8D4A200EA1276 /* Author.swift */; }; + 5053D08824B8D4D300EA1276 /* FirebaseConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08724B8D4D300EA1276 /* FirebaseConvertible.swift */; }; + 5053D08A24B8D54000EA1276 /* User+DictionaryRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08924B8D54000EA1276 /* User+DictionaryRepresentation.swift */; }; + 5053D08C24B8D73200EA1276 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08B24B8D73200EA1276 /* Comment.swift */; }; + 5053D08E24B8D91500EA1276 /* PostController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08D24B8D91500EA1276 /* PostController.swift */; }; + 5053D09024B8DA4300EA1276 /* SignInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D08F24B8DA4300EA1276 /* SignInViewController.swift */; }; + 5053D09424B8E72F00EA1276 /* LocationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D09324B8E72F00EA1276 /* LocationHelper.swift */; }; + 5053D09824B906C600EA1276 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D09724B906C600EA1276 /* MapViewController.swift */; }; + 5053D09C24B9134000EA1276 /* UIImage+Ratio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5053D09B24B9134000EA1276 /* UIImage+Ratio.swift */; }; + 50C45FB824B3988B000D1786 /* UIImage+Scaling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C45FB724B3988B000D1786 /* UIImage+Scaling.swift */; }; + 50C45FBA24B39E9F000D1786 /* RecordAudioViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C45FB924B39E9F000D1786 /* RecordAudioViewController.swift */; }; + 949D7232739C303905BB3022 /* Pods_MyExperiences.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E15FE4B1E43972FFA5255DE9 /* Pods_MyExperiences.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 085D4A00CE77781589B6193A /* Pods-MyExperiences.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MyExperiences.debug.xcconfig"; path = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences.debug.xcconfig"; sourceTree = ""; }; + 5020E59324B2F63900E70522 /* MyExperiences.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyExperiences.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5020E59624B2F63900E70522 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 5020E59824B2F63900E70522 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 5020E59D24B2F63900E70522 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 5020E59F24B2F63A00E70522 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 5020E5A224B2F63A00E70522 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 5020E5A424B2F63A00E70522 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5020E5AA24B2F8B000E70522 /* CreateANewExperienceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateANewExperienceViewController.swift; sourceTree = ""; }; + 5020E5AC24B2FBC300E70522 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 5053D08324B8D40700EA1276 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + 5053D08524B8D4A200EA1276 /* Author.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = ""; }; + 5053D08724B8D4D300EA1276 /* FirebaseConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseConvertible.swift; sourceTree = ""; }; + 5053D08924B8D54000EA1276 /* User+DictionaryRepresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+DictionaryRepresentation.swift"; sourceTree = ""; }; + 5053D08B24B8D73200EA1276 /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; + 5053D08D24B8D91500EA1276 /* PostController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostController.swift; sourceTree = ""; }; + 5053D08F24B8DA4300EA1276 /* SignInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInViewController.swift; sourceTree = ""; }; + 5053D09324B8E72F00EA1276 /* LocationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHelper.swift; sourceTree = ""; }; + 5053D09724B906C600EA1276 /* MapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = ""; }; + 5053D09B24B9134000EA1276 /* UIImage+Ratio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Ratio.swift"; sourceTree = ""; }; + 50C45FB724B3988B000D1786 /* UIImage+Scaling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Scaling.swift"; sourceTree = ""; }; + 50C45FB924B39E9F000D1786 /* RecordAudioViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordAudioViewController.swift; sourceTree = ""; }; + DE289047616DBA6AEE95B93A /* Pods-MyExperiences.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MyExperiences.release.xcconfig"; path = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences.release.xcconfig"; sourceTree = ""; }; + E15FE4B1E43972FFA5255DE9 /* Pods_MyExperiences.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MyExperiences.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5020E59024B2F63900E70522 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 949D7232739C303905BB3022 /* Pods_MyExperiences.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4624F59BE86BDDB0CD2E2D98 /* Pods */ = { + isa = PBXGroup; + children = ( + 085D4A00CE77781589B6193A /* Pods-MyExperiences.debug.xcconfig */, + DE289047616DBA6AEE95B93A /* Pods-MyExperiences.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 5020E58A24B2F63900E70522 = { + isa = PBXGroup; + children = ( + 5020E59524B2F63900E70522 /* MyExperiences */, + 5020E59424B2F63900E70522 /* Products */, + 4624F59BE86BDDB0CD2E2D98 /* Pods */, + D9172F0D3BE83362293E53B6 /* Frameworks */, + ); + sourceTree = ""; + }; + 5020E59424B2F63900E70522 /* Products */ = { + isa = PBXGroup; + children = ( + 5020E59324B2F63900E70522 /* MyExperiences.app */, + ); + name = Products; + sourceTree = ""; + }; + 5020E59524B2F63900E70522 /* MyExperiences */ = { + isa = PBXGroup; + children = ( + 5053D08224B8D3EC00EA1276 /* Models */, + 5053D07F24B8439600EA1276 /* Resources */, + 5020E5AC24B2FBC300E70522 /* GoogleService-Info.plist */, + 5053D08024B843A500EA1276 /* StoryBoards */, + 5020E5A424B2F63A00E70522 /* Info.plist */, + 5053D08124B843BC00EA1276 /* Helpers */, + 5053D07E24B8437800EA1276 /* ViewControllers */, + 5053D08724B8D4D300EA1276 /* FirebaseConvertible.swift */, + 5053D08924B8D54000EA1276 /* User+DictionaryRepresentation.swift */, + 5053D08D24B8D91500EA1276 /* PostController.swift */, + 5053D09324B8E72F00EA1276 /* LocationHelper.swift */, + 5053D09B24B9134000EA1276 /* UIImage+Ratio.swift */, + ); + path = MyExperiences; + sourceTree = ""; + }; + 5053D07E24B8437800EA1276 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + 5053D09724B906C600EA1276 /* MapViewController.swift */, + 5020E5AA24B2F8B000E70522 /* CreateANewExperienceViewController.swift */, + 50C45FB924B39E9F000D1786 /* RecordAudioViewController.swift */, + 5053D08F24B8DA4300EA1276 /* SignInViewController.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; + 5053D07F24B8439600EA1276 /* Resources */ = { + isa = PBXGroup; + children = ( + 5020E59624B2F63900E70522 /* AppDelegate.swift */, + 5020E59824B2F63900E70522 /* SceneDelegate.swift */, + 5020E59F24B2F63A00E70522 /* Assets.xcassets */, + ); + path = Resources; + sourceTree = ""; + }; + 5053D08024B843A500EA1276 /* StoryBoards */ = { + isa = PBXGroup; + children = ( + 5020E59C24B2F63900E70522 /* Main.storyboard */, + 5020E5A124B2F63A00E70522 /* LaunchScreen.storyboard */, + ); + path = StoryBoards; + sourceTree = ""; + }; + 5053D08124B843BC00EA1276 /* Helpers */ = { + isa = PBXGroup; + children = ( + 50C45FB724B3988B000D1786 /* UIImage+Scaling.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 5053D08224B8D3EC00EA1276 /* Models */ = { + isa = PBXGroup; + children = ( + 5053D08324B8D40700EA1276 /* Post.swift */, + 5053D08524B8D4A200EA1276 /* Author.swift */, + 5053D08B24B8D73200EA1276 /* Comment.swift */, + ); + path = Models; + sourceTree = ""; + }; + D9172F0D3BE83362293E53B6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E15FE4B1E43972FFA5255DE9 /* Pods_MyExperiences.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5020E59224B2F63900E70522 /* MyExperiences */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5020E5A724B2F63A00E70522 /* Build configuration list for PBXNativeTarget "MyExperiences" */; + buildPhases = ( + B1E992E6FE78715E95B58CCB /* [CP] Check Pods Manifest.lock */, + 5020E58F24B2F63900E70522 /* Sources */, + 5020E59024B2F63900E70522 /* Frameworks */, + 5020E59124B2F63900E70522 /* Resources */, + 7EEB14AE1E6E0C97B73A9E13 /* [CP] Embed Pods Frameworks */, + 1C4E2F75DC024E3F3CCD23D2 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MyExperiences; + productName = MyExperiences; + productReference = 5020E59324B2F63900E70522 /* MyExperiences.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5020E58B24B2F63900E70522 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1150; + LastUpgradeCheck = 1150; + ORGANIZATIONNAME = "Kelson Hartle"; + TargetAttributes = { + 5020E59224B2F63900E70522 = { + CreatedOnToolsVersion = 11.5; + }; + }; + }; + buildConfigurationList = 5020E58E24B2F63900E70522 /* Build configuration list for PBXProject "MyExperiences" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 5020E58A24B2F63900E70522; + productRefGroup = 5020E59424B2F63900E70522 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5020E59224B2F63900E70522 /* MyExperiences */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5020E59124B2F63900E70522 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5020E5A324B2F63A00E70522 /* LaunchScreen.storyboard in Resources */, + 5020E5AD24B2FBC300E70522 /* GoogleService-Info.plist in Resources */, + 5020E5A024B2F63A00E70522 /* Assets.xcassets in Resources */, + 5020E59E24B2F63900E70522 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1C4E2F75DC024E3F3CCD23D2 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7EEB14AE1E6E0C97B73A9E13 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B1E992E6FE78715E95B58CCB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-MyExperiences-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5020E58F24B2F63900E70522 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5020E59724B2F63900E70522 /* AppDelegate.swift in Sources */, + 50C45FBA24B39E9F000D1786 /* RecordAudioViewController.swift in Sources */, + 5053D08824B8D4D300EA1276 /* FirebaseConvertible.swift in Sources */, + 50C45FB824B3988B000D1786 /* UIImage+Scaling.swift in Sources */, + 5053D08E24B8D91500EA1276 /* PostController.swift in Sources */, + 5053D08424B8D40700EA1276 /* Post.swift in Sources */, + 5053D08C24B8D73200EA1276 /* Comment.swift in Sources */, + 5053D09424B8E72F00EA1276 /* LocationHelper.swift in Sources */, + 5053D09C24B9134000EA1276 /* UIImage+Ratio.swift in Sources */, + 5020E5AB24B2F8B000E70522 /* CreateANewExperienceViewController.swift in Sources */, + 5053D09024B8DA4300EA1276 /* SignInViewController.swift in Sources */, + 5053D08624B8D4A200EA1276 /* Author.swift in Sources */, + 5020E59924B2F63900E70522 /* SceneDelegate.swift in Sources */, + 5053D09824B906C600EA1276 /* MapViewController.swift in Sources */, + 5053D08A24B8D54000EA1276 /* User+DictionaryRepresentation.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 5020E59C24B2F63900E70522 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 5020E59D24B2F63900E70522 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 5020E5A124B2F63A00E70522 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 5020E5A224B2F63A00E70522 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 5020E5A524B2F63A00E70522 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 5020E5A624B2F63A00E70522 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5020E5A824B2F63A00E70522 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 085D4A00CE77781589B6193A /* Pods-MyExperiences.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 6WA5TYMFND; + INFOPLIST_FILE = MyExperiences/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.KelsonHartle.MyExperiences; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5020E5A924B2F63A00E70522 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE289047616DBA6AEE95B93A /* Pods-MyExperiences.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 6WA5TYMFND; + INFOPLIST_FILE = MyExperiences/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.KelsonHartle.MyExperiences; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5020E58E24B2F63900E70522 /* Build configuration list for PBXProject "MyExperiences" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5020E5A524B2F63A00E70522 /* Debug */, + 5020E5A624B2F63A00E70522 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5020E5A724B2F63A00E70522 /* Build configuration list for PBXNativeTarget "MyExperiences" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5020E5A824B2F63A00E70522 /* Debug */, + 5020E5A924B2F63A00E70522 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5020E58B24B2F63900E70522 /* Project object */; +} diff --git a/MyExperiences copy/MyExperiences.xcodeproj/xcshareddata/xcschemes/MyExperiences.xcscheme b/MyExperiences copy/MyExperiences.xcodeproj/xcshareddata/xcschemes/MyExperiences.xcscheme new file mode 100644 index 00000000..df9b4f6d --- /dev/null +++ b/MyExperiences copy/MyExperiences.xcodeproj/xcshareddata/xcschemes/MyExperiences.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/MyExperiences/FirebaseConvertible.swift b/MyExperiences copy/MyExperiences/FirebaseConvertible.swift new file mode 100644 index 00000000..552d61d6 --- /dev/null +++ b/MyExperiences copy/MyExperiences/FirebaseConvertible.swift @@ -0,0 +1,13 @@ +// +// FirebaseConvertible.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation + +protocol FirebaseConvertible { + var dictionaryRepresentation: [String: Any] { get } +} diff --git a/MyExperiences copy/MyExperiences/GoogleService-Info.plist b/MyExperiences copy/MyExperiences/GoogleService-Info.plist new file mode 100644 index 00000000..ea4b5745 --- /dev/null +++ b/MyExperiences copy/MyExperiences/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 148592290546-9n183to7ns2k73hb6pm403364enie3el.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.148592290546-9n183to7ns2k73hb6pm403364enie3el + API_KEY + AIzaSyAggmXqJCYTeVRwpnDZR13AVzxgDdnOc1s + GCM_SENDER_ID + 148592290546 + PLIST_VERSION + 1 + BUNDLE_ID + com.KelsonHartle.MyExperiences + PROJECT_ID + myexperiences-3d6b3 + STORAGE_BUCKET + myexperiences-3d6b3.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:148592290546:ios:3c782c7e0d88c6d5387e6b + DATABASE_URL + https://myexperiences-3d6b3.firebaseio.com + + \ No newline at end of file diff --git a/MyExperiences copy/MyExperiences/Helpers/UIImage+Scaling.swift b/MyExperiences copy/MyExperiences/Helpers/UIImage+Scaling.swift new file mode 100644 index 00000000..44ff560b --- /dev/null +++ b/MyExperiences copy/MyExperiences/Helpers/UIImage+Scaling.swift @@ -0,0 +1,39 @@ +// +// UIImage+Scaling.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/6/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import UIKit + +extension UIImage { + + /// Resize the image to a max dimension from size parameter + func imageByScaling(toSize size: CGSize) -> UIImage? { + guard size.width > 0 && size.height > 0 else { return nil } + + let originalAspectRatio = self.size.width/self.size.height + var correctedSize = size + + if correctedSize.width > correctedSize.width*originalAspectRatio { + correctedSize.width = correctedSize.width*originalAspectRatio + } else { + correctedSize.height = correctedSize.height/originalAspectRatio + } + + return UIGraphicsImageRenderer(size: correctedSize, format: imageRendererFormat).image { context in + draw(in: CGRect(origin: .zero, size: correctedSize)) + } + } + + /// Renders the image if the pixel data was rotated due to orientation of camera + var flattened: UIImage { + if imageOrientation == .up { return self } + return UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { context in + draw(at: .zero) + } + } +} diff --git a/MyExperiences copy/MyExperiences/Info.plist b/MyExperiences copy/MyExperiences/Info.plist new file mode 100644 index 00000000..4b978d71 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Info.plist @@ -0,0 +1,81 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + com.googleusercontent.apps.148592290546-9n183to7ns2k73hb6pm403364enie3el + + + + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSLocationWhenInUseUsageDescription + $(PRODUCT_NAME) We need to access your location in order to add geotags. + NSMicrophoneUsageDescription + ok? + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) We need acess to photos in order for you to post photos. + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/MyExperiences copy/MyExperiences/LocationHelper.swift b/MyExperiences copy/MyExperiences/LocationHelper.swift new file mode 100644 index 00000000..6b7a8e60 --- /dev/null +++ b/MyExperiences copy/MyExperiences/LocationHelper.swift @@ -0,0 +1,66 @@ +// +// LocationHelper.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import MapKit +import CoreLocation + +class LocationHelper: NSObject, CLLocationManagerDelegate { + + + static let shared = LocationHelper() + + private let locationManager = CLLocationManager() + var group: DispatchGroup? + + override init() { + super.init() + locationManager.delegate = self + + requestLocationAuthorization() + } + + func requestLocationAuthorization() { + + switch CLLocationManager.authorizationStatus() { + case .authorizedWhenInUse: + return + case .notDetermined: + locationManager.requestWhenInUseAuthorization() + default: + break + } + } + + func getCurrentLocation(completion: @escaping (CLLocationCoordinate2D?) -> Void) { + requestLocationAuthorization() + + group = DispatchGroup() + + group?.enter() + + locationManager.requestLocation() + + group?.notify(queue: .main) { + let coordinate = self.locationManager.location?.coordinate + + self.group = nil + completion(coordinate) + } + } + + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + group?.leave() + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + print("Failed getting location \(error)") + } + +} diff --git a/MyExperiences copy/MyExperiences/Models/Author.swift b/MyExperiences copy/MyExperiences/Models/Author.swift new file mode 100644 index 00000000..6f372961 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Models/Author.swift @@ -0,0 +1,38 @@ +// +// Author.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import FirebaseAuth + +struct Author: FirebaseConvertible, Equatable { + + init?(user: User) { + self.init(dictionary: user.dictionaryRepresentation) + } + + init?(dictionary: [String: Any]) { + guard let uid = dictionary[Author.uidKey] as? String, + let displayName = dictionary[Author.displayNameKey] as? String else { return nil } + + self.uid = uid + self.displayName = displayName + } + + + // MARK: - Properties + let uid: String + let displayName: String? + + private static let uidKey = "uid" + private static let displayNameKey = "displayName" + + var dictionaryRepresentation: [String: Any] { + return [Author.uidKey: uid, + Author.displayNameKey: displayName ?? "No display name"] + } +} diff --git a/MyExperiences copy/MyExperiences/Models/Comment.swift b/MyExperiences copy/MyExperiences/Models/Comment.swift new file mode 100644 index 00000000..c271c46e --- /dev/null +++ b/MyExperiences copy/MyExperiences/Models/Comment.swift @@ -0,0 +1,63 @@ +// +// Comment.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation + +import Foundation +import FirebaseAuth + +class Comment: FirebaseConvertible, Equatable { + + static private let textKey = "text" + static private let author = "author" + static private let timestampKey = "timestamp" + static private let audioKey = "audio" + + let text: String? + let author: Author + let timestamp: Date + let audioURL: URL? + + + init(text: String?, author: Author, timestamp: Date = Date(), audioURL: URL? = nil) { + self.text = text + self.author = author + self.timestamp = timestamp + self.audioURL = audioURL + } + + init?(dictionary: [String : Any]) { + guard let text = dictionary[Comment.textKey] as? String, + let authorDictionary = dictionary[Comment.author] as? [String: Any], + let author = Author(dictionary: authorDictionary), + let timestampTimeInterval = dictionary[Comment.timestampKey] as? TimeInterval else { return nil } + + self.text = text + self.author = author + self.timestamp = Date(timeIntervalSince1970: timestampTimeInterval) + + if let audioText = dictionary[Comment.audioKey] as? String { + self.audioURL = URL(string: audioText) + } else { + self.audioURL = nil + } + } + + var dictionaryRepresentation: [String: Any] { + return [Comment.textKey: text ?? "", + Comment.author: author.dictionaryRepresentation, + Comment.timestampKey: timestamp.timeIntervalSince1970, + Comment.audioKey : audioURL?.absoluteString ?? ""] + } + + static func ==(lhs: Comment, rhs: Comment) -> Bool { + return lhs.author == rhs.author && + lhs.timestamp == rhs.timestamp + } +} + diff --git a/MyExperiences copy/MyExperiences/Models/Post.swift b/MyExperiences copy/MyExperiences/Models/Post.swift new file mode 100644 index 00000000..75975dd2 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Models/Post.swift @@ -0,0 +1,108 @@ +// +// Post.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import FirebaseAuth +import MapKit + +enum MediaType: String { + case image + case video +} + +class Post: NSObject { + + + // MARK: - Properties + var mediaURL: URL + let mediaType: MediaType + let author: Author + let timestamp: Date + var comments: [Comment] + var id: String? + var ratio: CGFloat? + var geotag: CLLocationCoordinate2D? + var longitude: Double? + var latitude: Double? + + var title: String? { + return comments.first?.text + } + + static private let mediaKey = "media" + static private let ratioKey = "ratio" + static private let mediaTypeKey = "mediaType" + static private let authorKey = "author" + static private let commentsKey = "comments" + static private let timestampKey = "timestamp" + static private let idKey = "id" + + + init(title: String, mediaURL: URL, ratio: CGFloat? = nil, author: Author, mediaType: MediaType, timestamp: Date = Date()) { + self.mediaURL = mediaURL + self.ratio = ratio + self.mediaType = mediaType + self.author = author + self.comments = [Comment(text: title, author: author)] + self.timestamp = timestamp + } + + init?(dictionary: [String : Any], id: String) { + guard let mediaURLString = dictionary[Post.mediaKey] as? String, + let mediaURL = URL(string: mediaURLString), + let mediaTypeString = dictionary[Post.mediaTypeKey] as? String, + let mediaType = MediaType(rawValue: mediaTypeString), + let authorDictionary = dictionary[Post.authorKey] as? [String: Any], + let author = Author(dictionary: authorDictionary), + let timestampTimeInterval = dictionary[Post.timestampKey] as? TimeInterval, + let captionDictionaries = dictionary[Post.commentsKey] as? [[String: Any]] else { return nil } + + self.mediaURL = mediaURL + self.mediaType = mediaType + self.ratio = dictionary[Post.ratioKey] as? CGFloat + self.author = author + self.timestamp = Date(timeIntervalSince1970: timestampTimeInterval) + self.comments = captionDictionaries.compactMap({ Comment(dictionary: $0) }) + self.id = id + + if let lat = dictionary["lat"] as? Double, let lng = dictionary["lng"] as? Double { + self.geotag = CLLocationCoordinate2D(latitude: lat, longitude: lng) + } + } + + var dictionaryRepresentation: [String : Any] { + var dict: [String: Any] = [Post.mediaKey: mediaURL.absoluteString, + Post.mediaTypeKey: mediaType.rawValue, + Post.commentsKey: comments.map({ $0.dictionaryRepresentation }), + Post.authorKey: author.dictionaryRepresentation, + Post.timestampKey: timestamp.timeIntervalSince1970] + + + guard let ratio = self.ratio else { return dict } + + if let coordinate = self.geotag { + dict["lat"] = coordinate.latitude + dict["lng"] = coordinate.longitude + } + + dict[Post.ratioKey] = ratio + + return dict + } +} + +// MARK: - Extension +extension Post: MKAnnotation { + var coordinate: CLLocationCoordinate2D { + return geotag ?? CLLocationCoordinate2D() + } + + var subtitle: String? { + return author.displayName + } +} diff --git a/MyExperiences copy/MyExperiences/PostController.swift b/MyExperiences copy/MyExperiences/PostController.swift new file mode 100644 index 00000000..da2fe835 --- /dev/null +++ b/MyExperiences copy/MyExperiences/PostController.swift @@ -0,0 +1,178 @@ +// +// PostController.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import FirebaseAuth +import FirebaseDatabase +import FirebaseStorage +import MapKit +import CoreLocation + +class PostController { + + // MARK: - Properties + var posts: [Post] = [] + let currentUser = Auth.auth().currentUser + let postsRef = Database.database().reference().child("posts") + let storageRef = Storage.storage().reference() + + + // MARK: - Functions + + func createPost(with title: String, ofType mediaType: MediaType, mediaData: Data, ratio: CGFloat? = nil, geotag: CLLocationCoordinate2D? = nil, completion: @escaping (Bool) -> Void = { _ in }) { + + guard let currentUser = Auth.auth().currentUser, + let author = Author(user: currentUser) else { return } + let ref = storageRef.child(mediaType.rawValue) + + store(mediaData: mediaData, storage: ref) { (mediaURL) in + + guard let mediaURL = mediaURL else { completion(false); return } + + switch mediaType { + case .image: + let imagePost = Post(title: title, mediaURL: mediaURL, ratio: ratio, author: author, mediaType: mediaType) + imagePost.geotag = geotag + + self.postsRef.childByAutoId().setValue(imagePost.dictionaryRepresentation) { (error, ref) in + if let error = error { + NSLog("Error posting image post: \(error)") + completion(false) + } + completion(true) + } + case .video: + let videoPost = Post(title: title, mediaURL: mediaURL, ratio: ratio, author: author, mediaType: mediaType) + videoPost.geotag = geotag + + self.postsRef.childByAutoId().setValue(videoPost.dictionaryRepresentation) { (error, ref) in + if let error = error { + NSLog("Error posting image post: \(error)") + completion(false) + } + completion(true) + } + } + } + } + + func addComment(with text: String, to post: inout Post) { + + guard let currentUser = Auth.auth().currentUser, + let author = Author(user: currentUser) else { return } + + let comment = Comment(text: text, author: author) + post.comments.append(comment) + + savePostToFirebase(post) + } + + func addAudioComment(with comment: Comment, to post: inout Post) { + post.comments.append(comment) + savePostToFirebase(post) + + + + } + + func createAudioComment(with mediaData: Data, completion: @escaping (Comment?) -> Void = {_ in}) { + + guard let currentUser = Auth.auth().currentUser, + let author = Author(user: currentUser) else { return } + + let ref = storageRef.child("audio") + store(mediaData: mediaData, storage: ref) { (mediaURL) in + + guard let mediaURL = mediaURL else { completion(nil); return } + + let audioComment = Comment(text: nil, author: author, audioURL: mediaURL) + completion(audioComment) + + } + } + + func observePosts(completion: @escaping (Error?) -> Void) { + + postsRef.observe(.value, with: { (snapshot) in + + guard let postDictionaries = snapshot.value as? [String: [String: Any]] else { return } + + var posts: [Post] = [] + + + // Here is where the posts pulled down from the server are being sorted. + for (key, value) in postDictionaries { + + guard let post = Post(dictionary: value, id: key) else { continue } + + posts.append(post) + } + // Then they are sorted by timestamp with the newest timestamps being the first on the list being displayed first. + self.posts = posts.sorted(by: { $0.timestamp > $1.timestamp }) + + completion(nil) + + }) { (error) in + NSLog("Error fetching posts: \(error)") + } + } + + func savePostToFirebase(_ post: Post, completion: (Error?) -> Void = { _ in }) { + + guard let postID = post.id else { return } + + let ref = postsRef.child(postID) + + ref.setValue(post.dictionaryRepresentation) + } + + + //Here you can also change mediaType to Storage refrence. I guess that is what they are reffering to with this instruction + + /* + You can very easily change the store method to instead take in data and a StorageReference to accomodate for storing both Post media data and now the audio data as well. + */ + private func store(mediaData: Data, storage: StorageReference, completion: @escaping (URL?) -> Void) { + + let mediaID = UUID().uuidString + + let mediaRef = storage.child(mediaID) + + let uploadTask = mediaRef.putData(mediaData, metadata: nil) { (metadata, error) in + if let error = error { + NSLog("Error storing media data: \(error)") + completion(nil) + return + } + + //? ( DO NOT understand this code snippet below.) + if metadata == nil { + NSLog("No metadata returned from upload task.") + completion(nil) + return + } + + mediaRef.downloadURL(completion: { (url, error) in + + if let error = error { + NSLog("Error getting download url of media: \(error)") + } + + guard let url = url else { + NSLog("Download url is nil. Unable to create a Media object") + + completion(nil) + return + } + completion(url) + }) + } + + uploadTask.resume() + } +} diff --git a/MyExperiences copy/MyExperiences/Resources/AppDelegate.swift b/MyExperiences copy/MyExperiences/Resources/AppDelegate.swift new file mode 100644 index 00000000..61f70167 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Resources/AppDelegate.swift @@ -0,0 +1,64 @@ +// +// AppDelegate.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/6/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import Firebase +import GoogleSignIn + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + + FirebaseApp.configure() + + let signIn = GIDSignIn.sharedInstance() + signIn?.clientID = FirebaseApp.app()?.options.clientID + + if Auth.auth().currentUser != nil { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + let postsNavigationController = storyboard.instantiateViewController(withIdentifier: "InitialVC") + window?.rootViewController = postsNavigationController + window?.makeKeyAndVisible() + } + + return true + } + + func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, + withError error: Error!) { + if let error = error { + if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue { + print("Error: The user has not signed in before or they have since signed out.") + } else { + print("\(error.localizedDescription)") + } + return + } + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/00000.jpeg b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/00000.jpeg new file mode 100644 index 00000000..076f5361 Binary files /dev/null and b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/00000.jpeg differ diff --git a/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/Contents.json b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/Contents.json new file mode 100644 index 00000000..955b8508 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/00000.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "00000.jpeg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/Contents.json b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MyExperiences copy/MyExperiences/Resources/SceneDelegate.swift b/MyExperiences copy/MyExperiences/Resources/SceneDelegate.swift new file mode 100644 index 00000000..6fffef83 --- /dev/null +++ b/MyExperiences copy/MyExperiences/Resources/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/6/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/LaunchScreen.storyboard b/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/Main.storyboard b/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/Main.storyboard new file mode 100644 index 00000000..8895b741 --- /dev/null +++ b/MyExperiences copy/MyExperiences/StoryBoards/Base.lproj/Main.storyboard @@ -0,0 +1,390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/MyExperiences/UIImage+Ratio.swift b/MyExperiences copy/MyExperiences/UIImage+Ratio.swift new file mode 100644 index 00000000..605e9ba6 --- /dev/null +++ b/MyExperiences copy/MyExperiences/UIImage+Ratio.swift @@ -0,0 +1,16 @@ +// +// UIImage+Ratio.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import UIKit + +extension UIImage { + var ratio: CGFloat { + return size.height / size.width + } +} diff --git a/MyExperiences copy/MyExperiences/User+DictionaryRepresentation.swift b/MyExperiences copy/MyExperiences/User+DictionaryRepresentation.swift new file mode 100644 index 00000000..53b6f5cd --- /dev/null +++ b/MyExperiences copy/MyExperiences/User+DictionaryRepresentation.swift @@ -0,0 +1,21 @@ +// +// User+DictionaryRepresentation.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import Foundation +import FirebaseAuth + +extension User { + + private static let uidKey = "uid" + private static let displayNameKey = "displayName" + + var dictionaryRepresentation: [String: String] { + return [User.uidKey: uid, + User.displayNameKey: displayName ?? "No display name"] + } +} diff --git a/MyExperiences copy/MyExperiences/ViewControllers/CreateANewExperienceViewController.swift b/MyExperiences copy/MyExperiences/ViewControllers/CreateANewExperienceViewController.swift new file mode 100644 index 00000000..1eec4e5d --- /dev/null +++ b/MyExperiences copy/MyExperiences/ViewControllers/CreateANewExperienceViewController.swift @@ -0,0 +1,476 @@ +// +// CreateNewExperienceViewController.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/6/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import Photos +import CoreImage +import CoreImage.CIFilterBuiltins + + +// MARK: - Enumerations +enum FilterType { + case ciFalseColor + case ciEffectTonal + case ciEffectInstant + case ciSepiaTone + case ciZoomBlur + +} + + +class CreateANewExperienceViewController: UIViewController { + + // MARK: - Outlets + + @IBOutlet weak var recordButton: UIButton! + @IBOutlet weak var addPhotoButton: UIButton! + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var titleTextField: UITextField! + + @IBOutlet weak var ciZoomBlurSegmentedControl: UISegmentedControl! + @IBOutlet weak var ciZoomBlurSlider: UISlider! + @IBOutlet weak var falseColorOneSegmentedControl: UISegmentedControl! + @IBOutlet weak var falseColorTwoSegmentedControl: UISegmentedControl! + @IBOutlet weak var sepiaIntensitySlider: UISlider! + @IBOutlet weak var isGeoTaggedSwitch: UISwitch! + + // MARK: - Properties + var postController = PostController() + var imageData: Data? + var context = CIContext(options: nil) + var filterSelected: FilterType! + var colorOne: CIColor = .clear + var colorTwo: CIColor = .clear + + var ciZoomBlurCGPoint: CGPoint = CGPoint(x: 50, y: 150) + + + private var originalImage: UIImage? { + didSet { + // 414*3 = 1.242 pixels (portrait on iPhone 11 Pro Max) + guard let originalImage = originalImage else { + scaledImage = nil // clear out the image if it is nil + return + } + var scaledSize = imageView.bounds.size + let scale = UIScreen.main.scale //will let us know if it is a 1x 2x 3x + scaledSize = CGSize(width: scaledSize.width * scale, height: scaledSize.height * scale) + scaledImage = originalImage.imageByScaling(toSize: scaledSize) + } + } + + private var scaledImage: UIImage? { + didSet { + updateImage() + //saveButton.isHidden = false + } + } + + private func updateImage() { + if let scaledImage = scaledImage { + switch self.filterSelected { + case .ciZoomBlur: + imageView.image = filterPhoto(scaledImage, filterSelected: .ciZoomBlur) + case .ciFalseColor: + imageView.image = filterPhoto(scaledImage, filterSelected: .ciFalseColor) + case .ciEffectTonal: + imageView.image = filterPhoto(scaledImage, filterSelected: .ciEffectTonal) + case .ciEffectInstant: + imageView.image = filterPhoto(scaledImage, filterSelected: .ciEffectInstant) + case .ciSepiaTone: + imageView.image = filterPhoto(scaledImage, filterSelected: .ciSepiaTone) + case .none: + break + } + + } else { + imageView.image = nil + } + } + + + //MARK: - LIFE CYCLE + override func viewDidLoad() { + super.viewDidLoad() + + falseColorOneSegmentedControl.addTarget(self, action: #selector(didChangeColorIndexOne(_:)), for: .valueChanged) + falseColorTwoSegmentedControl.addTarget(self, action: #selector(didChangeColorIndexTwo(_:)), for: .valueChanged) + + ciZoomBlurSegmentedControl.addTarget(self, action: #selector(didChangeInputCenterPoint(_:)), for: .valueChanged) + + } + + override func viewWillAppear(_ animated: Bool) { + //Hide all buttons until needed + + //saveButton.isHidden = false + + falseColorOneSegmentedControl.isHidden = true + falseColorTwoSegmentedControl.isHidden = true + ciZoomBlurSlider.isHidden = true + ciZoomBlurSegmentedControl.isHidden = true + sepiaIntensitySlider.isHidden = true + + } + // MARK: - FILTERING + + func filterPhoto(_ image: UIImage, filterSelected: FilterType) -> UIImage? { + switch filterSelected { + case .ciFalseColor: + guard let cgImage = image.cgImage else { return nil } + + let ciImage = CIImage(cgImage: cgImage) + + let ciFalseColor = CIFilter.falseColor() + + ciFalseColor.inputImage = ciImage + ciFalseColor.color0 = colorOne + ciFalseColor.color1 = colorTwo + + guard let outputFalseColorFilterCIImage = ciFalseColor.outputImage else { return nil } + guard let falseColorFilterOutputImage = context.createCGImage(outputFalseColorFilterCIImage, from: CGRect(origin: .zero, size: image.size)) else { return nil } + + + return UIImage(cgImage: falseColorFilterOutputImage) + + case .ciEffectTonal: + guard let cgImage = image.cgImage else { return nil } + + let ciImage = CIImage(cgImage: cgImage) + + let ciEffectTonal = CIFilter.photoEffectTonal() + ciEffectTonal.inputImage = ciImage + guard let outputPhotoEffectTonal = ciEffectTonal.outputImage else { return nil } + + guard let outPutTonalCGImage = context.createCGImage(outputPhotoEffectTonal, from: CGRect(origin: .zero, size: image.size)) else { return image } + + return UIImage(cgImage: outPutTonalCGImage) + + case .ciEffectInstant: + guard let cgImage = image.cgImage else { return nil } + let ciImage = CIImage(cgImage: cgImage) + + let photoEffectInstant = CIFilter.photoEffectInstant() + photoEffectInstant.inputImage = ciImage + guard let photoEffectIntantOutputImage = photoEffectInstant.outputImage else { return image } + guard let outputPhotoEffectInstantCGImage = context.createCGImage(photoEffectIntantOutputImage, from: CGRect(origin: .zero, size: image.size)) else {return image} + + return UIImage(cgImage: outputPhotoEffectInstantCGImage) + + case .ciSepiaTone: + guard let cgImage = image.cgImage else { return nil } + let ciImage = CIImage(cgImage: cgImage) + + let sepiaTone = CIFilter.sepiaTone() + sepiaTone.inputImage = ciImage + sepiaTone.intensity = sepiaIntensitySlider.value + guard let sepiaToneOutPutCIImage = sepiaTone.outputImage else { return image } + guard let outPutCGCiSepiaToneImage = context.createCGImage(sepiaToneOutPutCIImage, from: CGRect(origin: .zero, size: image.size)) else {return image} + + + return UIImage(cgImage: outPutCGCiSepiaToneImage) + + case .ciZoomBlur: + guard let cgImage = image.cgImage else { return nil } + + let ciImage = CIImage(cgImage: cgImage) + + let zoomBlur = CIFilter.zoomBlur() + zoomBlur.inputImage = ciImage + zoomBlur.center = ciZoomBlurCGPoint + zoomBlur.amount = ciZoomBlurSlider.value + + guard let outputZoomBlur = zoomBlur.outputImage else { return nil } + guard let outPutCGZoomBlurImage = context.createCGImage(outputZoomBlur, from: CGRect(origin: .zero, size: image.size)) else {return image} + + + return UIImage(cgImage: outPutCGZoomBlurImage) + + } + } + + + //MARK: - OBJC functions for (CI FALSE COLOR) + @objc private func didChangeColorIndexOne(_ sender: UISegmentedControl) { + colorOne = determineColorOne() + updateImage() + } + + @objc private func didChangeColorIndexTwo(_ sender: UISegmentedControl) { + colorTwo = determineColorTwo() + updateImage() + } + + //HELPER FUNCTIONS + private func determineColorOne() -> CIColor { + // could use a guard let here later if necessary + + switch falseColorOneSegmentedControl.selectedSegmentIndex { + case 0: + colorOne = .green + case 1: + colorOne = .blue + case 2: + colorOne = .red + case 3: + colorOne = .magenta + default: + fatalError() + } + + return colorOne + } + + private func determineColorTwo() -> CIColor { + switch falseColorTwoSegmentedControl.selectedSegmentIndex { + case 0: + colorTwo = .cyan + case 1: + colorTwo = .gray + case 2: + colorTwo = .black + case 3: + colorTwo = .yellow + default: + fatalError() + } + return colorTwo + } + + //MARK: - END (CI FALSE COLOR) + + //MARK: - OBJC functions for (CI ZOOM BLUR) + @objc private func didChangeInputCenterPoint(_ sender: UISegmentedControl) { + ciZoomBlurCGPoint = determineZoomBlur() + updateImage() + } + @IBAction func didChangeZoomBlur(_ sender: Any) { + updateImage() + } + + private func determineZoomBlur() -> CGPoint { + switch ciZoomBlurSegmentedControl.selectedSegmentIndex { + case 0: + ciZoomBlurCGPoint = CGPoint(x: 10, y: 20) + case 1: + ciZoomBlurCGPoint = CGPoint(x: 50, y: 30) + case 2: + ciZoomBlurCGPoint = CGPoint(x: 120, y: 50) + case 3: + ciZoomBlurCGPoint = CGPoint(x: 60, y: 80) + case 4: + ciZoomBlurCGPoint = CGPoint(x: 200, y: 300) + default: + fatalError() + } + return ciZoomBlurCGPoint + } + + //MARK: - END (CI ZOOM BLUR) + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "CreateAudioCommentSegue" { + if let audioVC = segue.destination as? RecordAudioViewController { + audioVC.delegate = self + } + } + } + + + //MARK: - Sepia Tone + @IBAction func sepiaIntensitySlider(_ sender: Any) { + updateImage() + } + //MARK: - END (Sepia Tone) + + // MARK: - IBActions + + @IBAction func falseColorTapped(_ sender: Any) { + originalImage = imageView.image + filterSelected = .ciFalseColor + + falseColorOneSegmentedControl.isHidden = false + falseColorTwoSegmentedControl.isHidden = false + } + + @IBAction func tonalTapped(_ sender: Any) { + originalImage = imageView.image + filterSelected = .ciEffectTonal + } + + @IBAction func instantTapped(_ sender: Any) { + originalImage = imageView.image + filterSelected = .ciEffectInstant + } + + @IBAction func sepiaTapped(_ sender: Any) { + originalImage = imageView.image + filterSelected = .ciSepiaTone + sepiaIntensitySlider.isHidden = false + sepiaIntensitySlider.minimumTrackTintColor = .lightGray + sepiaIntensitySlider.maximumTrackTintColor = .brown + } + + @IBAction func zoomBlurTapped(_ sender: Any) { + originalImage = imageView.image + filterSelected = .ciZoomBlur + + ciZoomBlurSlider.isHidden = false + ciZoomBlurSegmentedControl.isHidden = false + + } + + + @IBAction func addPhotoTapped(_ sender: Any) { + let authorizationStatus = PHPhotoLibrary.authorizationStatus() + + switch authorizationStatus { + case .authorized: + presentImagePickerController() + case .notDetermined: + + PHPhotoLibrary.requestAuthorization { (status) in + + guard status == .authorized else { + NSLog("User did not authorize access to the photo library") + + return + } + + self.presentImagePickerController() + } + + case .denied: + return + case .restricted: + return + + @unknown default: + print("FatalError") + } + presentImagePickerController() + } + + @IBAction func createExperienceButtonTapped(_ sender: Any) { + + view.endEditing(true) + guard let imageData = imageView.image?.jpegData(compressionQuality: 0.1), + let title = titleTextField.text, title != "" else { + print("ERROR") + return + } + + if isGeoTaggedSwitch.isOn { + LocationHelper.shared.getCurrentLocation { (coordinate) in + self.postController.createPost(with: title, ofType: .image, mediaData: imageData, ratio: self.imageView.image?.ratio, geotag: coordinate) { (success) in + guard success else { + + return + } + } + DispatchQueue.main.async { + self.navigationController?.popViewController(animated: true) + } + } + } else { + postController.createPost(with: title, ofType: .image, mediaData: imageData, ratio: imageView.image?.ratio, geotag: nil) { (success) in + guard success else { + + return + } + } + } + } + + + + // MARK: - AUDIO + + var audioPlayer: AVAudioPlayer? + private var audioData: Data? + + func setAudioData(data: Data?) { + audioData = data + } + + func playRecording(with audioData: Data) { + do { + audioPlayer = try AVAudioPlayer(data: audioData) + audioPlayer?.delegate = self + audioPlayer?.prepareToPlay() + audioPlayer?.play() + } catch { + print("Error Playing Audio Data") + } + } + + @IBAction func playRecording(_ sender: Any) { + guard let audioData = audioData else { return } + playRecording(with: audioData) + + } + + //MARK: - Image picker helper functions + private func presentImagePickerController() { + + guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { + return + } + + DispatchQueue.main.async { + let imagePicker = UIImagePickerController() + + imagePicker.delegate = self + + imagePicker.sourceType = .photoLibrary + + self.present(imagePicker, animated: true, completion: nil) + } + } +} + +//MARK: - UI image / navigation controller delegates + +extension CreateANewExperienceViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { + + func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { + + addPhotoButton.setTitle("", for: []) + + picker.dismiss(animated: true, completion: nil) + + guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return } + + imageView.image = image + + //setImageViewHeight(with: image.ratio) + } + + func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { + picker.dismiss(animated: true, completion: nil) + } +} + +extension CreateANewExperienceViewController: AudioCommentViewControllerDelegate { + func saveAudioCommentButtonWasTapped(_ audioData: Data, _ viewController: UIViewController) { + setAudioData(data: audioData) + + viewController.dismiss(animated: true, completion: nil) + } +} + +extension CreateANewExperienceViewController: AVAudioPlayerDelegate { + + func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + } + + func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { + if let error = error { + print("Audio Player error: \(error)") + } + } +} diff --git a/MyExperiences copy/MyExperiences/ViewControllers/MapViewController.swift b/MyExperiences copy/MyExperiences/ViewControllers/MapViewController.swift new file mode 100644 index 00000000..85889535 --- /dev/null +++ b/MyExperiences copy/MyExperiences/ViewControllers/MapViewController.swift @@ -0,0 +1,83 @@ + // +// MapViewController.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import CoreLocation +import MapKit + +class MapViewController: UIViewController { + + // MARK: - Properties + + var postController = PostController() + + @IBOutlet weak var mapView: MKMapView! + + private let annotationReuseIdentifier = "PostAnnotationView" + private var posts: [Post] = [] { + didSet { + let oldPosts = Set(oldValue) + let newPosts = Set(self.posts) + let addedPosts = Array(newPosts.subtracting(oldPosts)) + let removedPosts = Array(oldPosts.subtracting(newPosts)) + mapView.removeAnnotations(removedPosts) + mapView.addAnnotations(addedPosts) + mapView.showAnnotations(self.posts, animated: true) + } + } + + + // MARK: - LifeCycle + override func viewDidLoad() { + + super.viewDidLoad() + self.mapView.showsUserLocation = true + self.mapView.delegate = self + self.mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: annotationReuseIdentifier) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + postController.observePosts { (_) in + print("TEST WORKED") + for post in self.postController.posts where post.geotag != nil { + self.posts.append(post) + } + } + + } +} + + + // MARK: - Extensions + extension MapViewController: MKMapViewDelegate { + func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) { + + } + + func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { + guard let post = annotation as? Post else { return nil } + + guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationReuseIdentifier, for: post) as? MKMarkerAnnotationView else { + fatalError("Missing registered map annotation view") + } + + annotationView.canShowCallout = true + annotationView.animatesWhenAdded = true + annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) + + return annotationView + } + +// func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { +// guard let post = view.annotation as? Post else { return } +// +// // self.performSegue(withIdentifier: "DetailSegue", sender: post) +// } + } diff --git a/MyExperiences copy/MyExperiences/ViewControllers/RecordAudioViewController.swift b/MyExperiences copy/MyExperiences/ViewControllers/RecordAudioViewController.swift new file mode 100644 index 00000000..6882ddcf --- /dev/null +++ b/MyExperiences copy/MyExperiences/ViewControllers/RecordAudioViewController.swift @@ -0,0 +1,226 @@ +// +// RecordAudioViewController.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/6/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import AVFoundation + +// MARK: - Protocols +protocol AudioCommentViewControllerDelegate { + func saveAudioCommentButtonWasTapped(_ audioData: Data, _ viewController: UIViewController) +} + +class RecordAudioViewController: UIViewController { + + // MARK: - Properties + var delegate: AudioCommentViewControllerDelegate? + + // MARK: - Outlets + @IBOutlet weak var recordButton: UIButton! + @IBOutlet weak var playButton: UIButton! + @IBOutlet weak var timeAllotedLabel: UILabel! + @IBOutlet weak var timeRemainingLabel: UILabel! + @IBOutlet weak var timeSlider: UISlider! + + private lazy var timeFormatter: DateComponentsFormatter = { + let formatting = DateComponentsFormatter() + formatting.unitsStyle = .positional // 00:00 mm:ss + // NOTE: DateComponentFormatter is good for minutes/hours/seconds + // DateComponentsFormatter not good for milliseconds, use DateFormatter instead) + formatting.zeroFormattingBehavior = .pad + formatting.allowedUnits = [.minute, .second] + return formatting + }() + + // MARK: - LifeCycle + + override func viewDidLoad() { + super.viewDidLoad() + + timeAllotedLabel.font = UIFont.monospacedDigitSystemFont(ofSize: timeAllotedLabel.font.pointSize, + weight: .regular) + timeRemainingLabel.font = UIFont.monospacedDigitSystemFont(ofSize: timeRemainingLabel.font.pointSize, + weight: .regular) + updateViews() + } + + @IBAction func saveAudioCommentButtonTapped(_ sender: UIButton) { + guard let recordURL = recordURL else { return } + do { + let audioData = try Data(contentsOf: recordURL) + delegate?.saveAudioCommentButtonWasTapped(audioData, self) + } catch { + print("Error creating audio data from url") + } + } + + // MARK: - Audio + // Playback APIs + var audioPlayer: AVAudioPlayer? + + var timer: Timer? + + private func loadAudio() { + let songURL = Bundle.main.url(forResource: "piano", withExtension: "mp3")! + + audioPlayer = try! AVAudioPlayer(contentsOf: songURL) // FIXME: catch error and print + audioPlayer?.delegate = self + } + + var isPlaying: Bool { + audioPlayer?.isPlaying ?? false + } + + func play() { + audioPlayer?.play() + updateViews() + startTimer() + } + + func pause() { + audioPlayer?.pause() + updateViews() + cancelTimer() + } + + func playPause() { + if isPlaying { + pause() + } else { + play() + } + } + + private func startTimer() { + cancelTimer() + timer = Timer.scheduledTimer(timeInterval: 0.03, + target: self, + selector: #selector(updateTimer(timer:)), + userInfo: nil, + repeats: true) + } + + @objc private func updateTimer(timer: Timer) { + updateViews() + } + + private func cancelTimer() { + timer?.invalidate() + timer = nil + } + + + @IBAction func playButtonPressed(_ sender: Any) { + playPause() + } + + // Record APIs + + var audioRecorder: AVAudioRecorder? + var recordURL: URL? + + var isRecording: Bool { + return audioRecorder?.isRecording ?? false + } + + func record() { + let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + let name = ISO8601DateFormatter.string(from: Date(), timeZone: .current, formatOptions: [.withInternetDateTime]) + + let file = documents.appendingPathComponent(name).appendingPathExtension("caf") + recordURL = file + + print("record: \(file)") + + // 44.1 KHz 44,100 samples per second + let format = AVAudioFormat(standardFormatWithSampleRate: 44_100, channels: 1)! // FIXME: error handling + + audioRecorder = try! AVAudioRecorder(url: file, format: format) // FIXME: try! + audioRecorder?.delegate = self + audioRecorder?.record() + updateViews() + } + + func stop() { + audioRecorder?.stop() + audioRecorder = nil + updateViews() + } + + func recordToggle() { + if isRecording { + stop() + } else { + record() + } + } + + @IBAction func recordButtonPressed(_ sender: Any) { + recordToggle() + } + + // MARK: - Private Functions + private func updateViews() { + let playButtonTitle = isPlaying ? "Pause" : "Play" + playButton.setTitle(playButtonTitle, for: .normal) + + let elapsedTime = audioPlayer?.currentTime ?? 0 + let duration = audioPlayer?.duration ?? 0 + timeAllotedLabel.text = timeFormatter.string(from: elapsedTime) + + timeSlider.minimumValue = 0 + timeSlider.maximumValue = Float(duration) + timeSlider.value = Float(elapsedTime) + + let recordButtonTitle = isRecording ? "Stop" : "Record" + recordButton.setTitle(recordButtonTitle, for: .normal) + + let timeRemaining = duration - elapsedTime + timeRemainingLabel.text = timeFormatter.string(from: timeRemaining) + } + +} + +// MARK: - Extensions +extension RecordAudioViewController: AVAudioPlayerDelegate { + + func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { + updateViews() + } + + func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { + if let error = error { + print("Audio Player error: \(error)") + } + } +} + +// TODO: Store the fileURL +// TODO: Get permission to record audio + +extension RecordAudioViewController: AVAudioRecorderDelegate { + + func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) { + if let error = error { + print("Audio recorder error: \(error)") + } + } + + func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { + + // TODO: Update player to load our audio file + print("Finished Recording") + if let recordURL = recordURL { + audioPlayer = try! AVAudioPlayer(contentsOf: recordURL) // FIXME: try! + audioPlayer?.delegate = self + updateViews() + } + + } + +} diff --git a/MyExperiences copy/MyExperiences/ViewControllers/SignInViewController.swift b/MyExperiences copy/MyExperiences/ViewControllers/SignInViewController.swift new file mode 100644 index 00000000..be0c06a3 --- /dev/null +++ b/MyExperiences copy/MyExperiences/ViewControllers/SignInViewController.swift @@ -0,0 +1,76 @@ +// +// SignInViewController.swift +// MyExperiences +// +// Created by Kelson Hartle on 7/10/20. +// Copyright © 2020 Kelson Hartle. All rights reserved. +// + +import UIKit +import Firebase +import GoogleSignIn + +class SignInViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + GIDSignIn.sharedInstance()?.presentingViewController = self + GIDSignIn.sharedInstance()?.delegate = self + + setUpSignInButton() + } + + @IBAction func googleSignIn(_ sender: Any) { + GIDSignIn.sharedInstance()?.signIn() + } +} + +extension SignInViewController: GIDSignInDelegate { + func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { + + if let error = error { + print("Error signing in with Google: \(error)") + return + } + + guard let authentication = user.authentication else { return } + + let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken) + + Auth.auth().signIn(with: credential) { (authResult, error) in + if let error = error { + print("Error signing in with Google: \(error)") + return + } + + DispatchQueue.main.async { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + let postsNavigationController = storyboard.instantiateViewController(withIdentifier: "InitialVC") + postsNavigationController.modalPresentationStyle = .fullScreen + self.present(postsNavigationController, animated: false, completion: nil) + } + } + } + + func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) { + print("User disconnected") + } + + func setUpSignInButton() { + + let button = GIDSignInButton() + + button.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(button) + + + let buttonCenterXConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor) + let buttonCenterYConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor) + let buttonWidthConstraint = button.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5) + + view.addConstraints([buttonCenterXConstraint, + buttonCenterYConstraint, + buttonWidthConstraint]) + } +} diff --git a/MyExperiences copy/Podfile b/MyExperiences copy/Podfile new file mode 100644 index 00000000..09a88b0f --- /dev/null +++ b/MyExperiences copy/Podfile @@ -0,0 +1,16 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'MyExperiences' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for MyExperiences + pod 'Firebase/Core' + pod 'Firebase/Database' + pod 'Firebase/Storage' + pod 'Firebase/Auth' + pod 'FirebaseUI/Google' + pod 'GoogleSignIn' + +end diff --git a/MyExperiences copy/Podfile.lock b/MyExperiences copy/Podfile.lock new file mode 100644 index 00000000..28c8297b --- /dev/null +++ b/MyExperiences copy/Podfile.lock @@ -0,0 +1,165 @@ +PODS: + - AppAuth (1.4.0): + - AppAuth/Core (= 1.4.0) + - AppAuth/ExternalUserAgent (= 1.4.0) + - AppAuth/Core (1.4.0) + - AppAuth/ExternalUserAgent (1.4.0) + - Firebase/Auth (6.27.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 6.6.0) + - Firebase/Core (6.27.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.6.1) + - Firebase/CoreOnly (6.27.0): + - FirebaseCore (= 6.8.0) + - Firebase/Database (6.27.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.3.0) + - Firebase/Storage (6.27.0): + - Firebase/CoreOnly + - FirebaseStorage (~> 3.7.0) + - FirebaseAnalytics (6.6.1): + - FirebaseCore (~> 6.8) + - FirebaseInstallations (~> 1.4) + - GoogleAppMeasurement (= 6.6.1) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 1.30905.0) + - FirebaseAuth (6.6.0): + - FirebaseCore (~> 6.8) + - GoogleUtilities/AppDelegateSwizzler (~> 6.5) + - GoogleUtilities/Environment (~> 6.5) + - GTMSessionFetcher/Core (~> 1.1) + - FirebaseCore (6.8.0): + - FirebaseCoreDiagnostics (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.4.0): + - GoogleDataTransportCCTSupport (~> 3.1) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 1.30905.0) + - FirebaseDatabase (6.3.0): + - FirebaseCore (~> 6.8) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.4.0): + - FirebaseCore (~> 6.8) + - GoogleUtilities/Environment (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.6) + - PromisesObjC (~> 1.2) + - FirebaseStorage (3.7.0): + - FirebaseCore (~> 6.8) + - GTMSessionFetcher/Core (~> 1.1) + - FirebaseUI/Auth (8.4.2): + - Firebase/Auth (~> 6.0) + - GoogleUtilities/UserDefaults + - FirebaseUI/Google (8.4.2): + - FirebaseUI/Auth + - GoogleSignIn (~> 5.0) + - GoogleAppMeasurement (6.6.1): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 1.30905.0) + - GoogleDataTransport (6.2.1) + - GoogleDataTransportCCTSupport (3.2.0): + - GoogleDataTransport (~> 6.1) + - nanopb (~> 1.30905.0) + - GoogleSignIn (5.0.2): + - AppAuth (~> 1.2) + - GTMAppAuth (~> 1.0) + - GTMSessionFetcher/Core (~> 1.1) + - GoogleUtilities/AppDelegateSwizzler (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.6.0): + - PromisesObjC (~> 1.2) + - GoogleUtilities/Logger (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.6.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.6.0)" + - GoogleUtilities/Reachability (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.6.0): + - GoogleUtilities/Logger + - GTMAppAuth (1.0.0): + - AppAuth/Core (~> 1.0) + - GTMSessionFetcher (~> 1.1) + - GTMSessionFetcher (1.4.0): + - GTMSessionFetcher/Full (= 1.4.0) + - GTMSessionFetcher/Core (1.4.0) + - GTMSessionFetcher/Full (1.4.0): + - GTMSessionFetcher/Core (= 1.4.0) + - leveldb-library (1.22) + - nanopb (1.30905.0): + - nanopb/decode (= 1.30905.0) + - nanopb/encode (= 1.30905.0) + - nanopb/decode (1.30905.0) + - nanopb/encode (1.30905.0) + - PromisesObjC (1.2.9) + +DEPENDENCIES: + - Firebase/Auth + - Firebase/Core + - Firebase/Database + - Firebase/Storage + - FirebaseUI/Google + - GoogleSignIn + +SPEC REPOS: + trunk: + - AppAuth + - Firebase + - FirebaseAnalytics + - FirebaseAuth + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseDatabase + - FirebaseInstallations + - FirebaseStorage + - FirebaseUI + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7 + Firebase: fc4cbf6f1592636431821ef9a3c557e4dfd9f268 + FirebaseAnalytics: 0ea640473474f036cabbc2576e20c2d63671c92f + FirebaseAuth: b85c064e0ac60f82486728d50a4803f235687302 + FirebaseCore: feda061cb1ee6d8ad4824f4a4a8ffbcfe284f595 + FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84 + FirebaseDatabase: 3d02ffa794ec174853c086cf87cf2dc79bd6da49 + FirebaseInstallations: 293f567159b6d66d1c990f13bb868066096c94ec + FirebaseStorage: af7bdbd12177cf567df00904e3e3a93704f25b15 + FirebaseUI: e57e9b9c4340631151fbe67a14206d23d0974f37 + GoogleAppMeasurement: 2fd5c5a56c069db635c8e7b92d4809a9591d0a69 + GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 + GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d + GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213 + GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 + GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e + GTMSessionFetcher: 6f5c8abbab8a9bce4bb3f057e317728ec6182b10 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 + PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75 + +PODFILE CHECKSUM: 4195f04b27b7f552f1bacbf30465a5eb43adf594 + +COCOAPODS: 1.9.3 diff --git a/MyExperiences copy/Pods/AppAuth/LICENSE b/MyExperiences copy/Pods/AppAuth/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/AppAuth/README.md b/MyExperiences copy/Pods/AppAuth/README.md new file mode 100644 index 00000000..5f54c2c3 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/README.md @@ -0,0 +1,574 @@ +![AppAuth for iOS and macOS](https://rawgit.com/openid/AppAuth-iOS/master/appauth_lockup.svg) +[![Build Status](https://travis-ci.org/openid/AppAuth-iOS.svg?branch=master)](https://travis-ci.org/openid/AppAuth-iOS) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) + +AppAuth for iOS and macOS is a client SDK for communicating with +[OAuth 2.0](https://tools.ietf.org/html/rfc6749) and +[OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) providers. +It strives to +directly map the requests and responses of those specifications, while following +the idiomatic style of the implementation language. In addition to mapping the +raw protocol flows, convenience methods are available to assist with common +tasks like performing an action with fresh tokens. + +It follows the best practices set out in +[RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252) +including using `SFAuthenticationSession` and `SFSafariViewController` on iOS +for the auth request. `UIWebView` and `WKWebView` are explicitly *not* +supported due to the security and usability reasons explained in +[Section 8.12 of RFC 8252](https://tools.ietf.org/html/rfc8252#section-8.12). + +It also supports the [PKCE](https://tools.ietf.org/html/rfc7636) extension to +OAuth, which was created to secure authorization codes in public clients when +custom URI scheme redirects are used. The library is friendly to other +extensions (standard or otherwise), with the ability to handle additional params +in all protocol requests and responses. + +## Specification + +### iOS + +#### Supported Versions + +AppAuth supports iOS 7 and above. + +iOS 9+ uses the in-app browser tab pattern +(via `SFSafariViewController`), and falls back to the system browser (mobile +Safari) on earlier versions. + +#### Authorization Server Requirements + +Both Custom URI Schemes (all supported versions of iOS) and Universal Links +(iOS 9+) can be used with the library. + +In general, AppAuth can work with any authorization server that supports +native apps, as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252), +either through custom URI scheme redirects, or universal links. +Authorization servers that assume all clients are web-based, or require clients to maintain +confidentiality of the client secrets may not work well. + +### macOS + +#### Supported Versions + +AppAuth supports macOS (OS X) 10.9 and above. + +#### Authorization Server Requirements + +AppAuth for macOS supports both custom schemes; a loopback HTTP redirects +via a small embedded server. + +In general, AppAuth can work with any authorization server that supports +native apps, as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252); +either through custom URI schemes, or loopback HTTP redirects. +Authorization servers that assume all clients are web-based, or require clients to maintain +confidentiality of the client secrets may not work well. + +## Try + +Want to try out AppAuth? Just run: + + pod try AppAuth + +Follow the instructions in [Examples/README.md](Examples/README.md) to configure +with your own OAuth client (you need to update three configuration points with your +client info to try the demo). + +## Setup + +AppAuth supports four options for dependency management. + +### Swift Package Manager + +With [Swift Package Manager](https://swift.org/package-manager), +add the following `dependency` to your `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/openid/AppAuth-iOS.git", .upToNextMajor(from: "1.3.0")) +] +``` + +### CocoaPods + +With [CocoaPods](https://guides.cocoapods.org/using/getting-started.html), +add the following line to your `Podfile`: + + pod 'AppAuth' + +Then, run `pod install`. + +### Carthage + +With [Carthage](https://github.com/Carthage/Carthage), add the following +line to your `Cartfile`: + + github "openid/AppAuth-iOS" "master" + +Then, run `carthage bootstrap`. + +### Static Library + +You can also use AppAuth as a static library. This requires linking the library +and your project, and including the headers. Here is a suggested configuration: + +1. Create an Xcode Workspace. +2. Add `AppAuth.xcodeproj` to your Workspace. +3. Include libAppAuth as a linked library for your target (in the "General -> +Linked Framework and Libraries" section of your target). +4. Add `AppAuth-iOS/Source` to your search paths of your target ("Build Settings -> +"Header Search Paths"). + +## Auth Flow + +AppAuth supports both manual interaction with the authorization server +where you need to perform your own token exchanges, as well as convenience +methods that perform some of this logic for you. This example uses the +convenience method, which returns either an `OIDAuthState` object, or an error. + +`OIDAuthState` is a class that keeps track of the authorization and token +requests and responses, and provides a convenience method to call an API with +fresh tokens. This is the only object that you need to serialize to retain the +authorization state of the session. + +### Configuration + +You can configure AppAuth by specifying the endpoints directly: + +Objective-C +```objc +NSURL *authorizationEndpoint = + [NSURL URLWithString:@"https://accounts.google.com/o/oauth2/v2/auth"]; +NSURL *tokenEndpoint = + [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"]; + +OIDServiceConfiguration *configuration = + [[OIDServiceConfiguration alloc] + initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint]; + +// perform the auth request... +``` + +Swift +```swift +let authorizationEndpoint = URL(string: "https://accounts.google.com/o/oauth2/v2/auth")! +let tokenEndpoint = URL(string: "https://www.googleapis.com/oauth2/v4/token")! +let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint, + tokenEndpoint: tokenEndpoint) + +// perform the auth request... +``` + +Or through discovery: + +Objective-C +```objc +NSURL *issuer = [NSURL URLWithString:@"https://accounts.google.com"]; + +[OIDAuthorizationService discoverServiceConfigurationForIssuer:issuer + completion:^(OIDServiceConfiguration *_Nullable configuration, + NSError *_Nullable error) { + + if (!configuration) { + NSLog(@"Error retrieving discovery document: %@", + [error localizedDescription]); + return; + } + + // perform the auth request... +}]; +``` + +Swift +```swift +let issuer = URL(string: "https://accounts.google.com")! + +// discovers endpoints +OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in + guard let config = configuration else { + print("Error retrieving discovery document: \(error?.localizedDescription ?? "Unknown error")") + return + } + + // perform the auth request... +} +``` + +### Authorizing – iOS + +First, you need to have a property in your `UIApplicationDelegate` +implementation to hold the session, in order to continue the authorization flow +from the redirect. In this example, the implementation of this delegate is +a class named `AppDelegate`, if your app's application delegate has a different +name, please update the class name in samples below accordingly. + +Objective-C +```objc +@interface AppDelegate : UIResponder +// property of the app's AppDelegate +@property(nonatomic, strong, nullable) id currentAuthorizationFlow; +@end +``` + +Swift +```swift +class AppDelegate: UIResponder, UIApplicationDelegate { + // property of the app's AppDelegate + var currentAuthorizationFlow: OIDExternalUserAgentSession? +} +``` + + +And your main class, a property to store the auth state: + +Objective-C +```objc +// property of the containing class +@property(nonatomic, strong, nullable) OIDAuthState *authState; +``` +Swift +```swift +// property of the containing class +private var authState: OIDAuthState? +``` + + +Then, initiate the authorization request. By using the +`authStateByPresentingAuthorizationRequest` convenience method, the token +exchange will be performed automatically, and everything will be protected with +PKCE (if the server supports it). AppAuth also lets you perform these +requests manually. See the `authNoCodeExchange` method in the included Example +app for a demonstration: + +Objective-C +```objc +// builds authentication request +OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration + clientId:kClientID + scopes:@[OIDScopeOpenID, + OIDScopeProfile] + redirectURL:kRedirectURI + responseType:OIDResponseTypeCode + additionalParameters:nil]; + +// performs authentication request +AppDelegate *appDelegate = + (AppDelegate *)[UIApplication sharedApplication].delegate; +appDelegate.currentAuthorizationFlow = + [OIDAuthState authStateByPresentingAuthorizationRequest:request + presentingViewController:self + callback:^(OIDAuthState *_Nullable authState, + NSError *_Nullable error) { + if (authState) { + NSLog(@"Got authorization tokens. Access token: %@", + authState.lastTokenResponse.accessToken); + [self setAuthState:authState]; + } else { + NSLog(@"Authorization error: %@", [error localizedDescription]); + [self setAuthState:nil]; + } +}]; +``` + +Swift +```swift +// builds authentication request +let request = OIDAuthorizationRequest(configuration: configuration, + clientId: clientID, + clientSecret: clientSecret, + scopes: [OIDScopeOpenID, OIDScopeProfile], + redirectURL: redirectURI, + responseType: OIDResponseTypeCode, + additionalParameters: nil) + +// performs authentication request +print("Initiating authorization request with scope: \(request.scope ?? "nil")") + +let appDelegate = UIApplication.shared.delegate as! AppDelegate + +appDelegate.currentAuthorizationFlow = + OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in + if let authState = authState { + self.setAuthState(authState) + print("Got authorization tokens. Access token: " + + "\(authState.lastTokenResponse?.accessToken ?? "nil")") + } else { + print("Authorization error: \(error?.localizedDescription ?? "Unknown error")") + self.setAuthState(nil) + } +} +``` + +*Handling the Redirect* + +The authorization response URL is returned to the app via the iOS openURL +app delegate method, so you need to pipe this through to the current +authorization session (created in the previous session): + +Objective-C +```objc +- (BOOL)application:(UIApplication *)app + openURL:(NSURL *)url + options:(NSDictionary *)options { + // Sends the URL to the current authorization flow (if any) which will + // process it if it relates to an authorization response. + if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { + _currentAuthorizationFlow = nil; + return YES; + } + + // Your additional URL handling (if any) goes here. + + return NO; +} +``` + +Swift +```swift +func application(_ app: UIApplication, + open url: URL, + options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { + // Sends the URL to the current authorization flow (if any) which will + // process it if it relates to an authorization response. + if let authorizationFlow = self.currentAuthorizationFlow, + authorizationFlow.resumeExternalUserAgentFlow(with: url) { + self.currentAuthorizationFlow = nil + return true + } + + // Your additional URL handling (if any) + + return false +} +``` + +### Authorizing – MacOS + +On macOS, the most popular way to get the authorization response redirect is to +start a local HTTP server on the loopback interface (limited to incoming +requests from the user's machine only). When the authorization is complete, the +user is redirected to that local server, and the authorization response can be +processed by the app. AppAuth takes care of managing the local HTTP server +lifecycle for you. + +> #### :bulb: Alternative: Custom URI Schemes +> Custom URI schemes are also supported on macOS, but some browsers display +> an interstitial, which reduces the usability. For an example on using custom +> URI schemes with macOS, See `Example-Mac`. + +To receive the authorization response using a local HTTP server, first you need +to have an instance variable in your main class to retain the HTTP redirect +handler: + +Objective-C +```objc +OIDRedirectHTTPHandler *_redirectHTTPHandler; +``` + +Then, as the port used by the local HTTP server varies, you need to start it +before building the authorization request, in order to get the exact redirect +URI to use: + +Objective-C +```objc +static NSString *const kSuccessURLString = + @"http://openid.github.io/AppAuth-iOS/redirect/"; +NSURL *successURL = [NSURL URLWithString:kSuccessURLString]; + +// Starts a loopback HTTP redirect listener to receive the code. This needs to be started first, +// as the exact redirect URI (including port) must be passed in the authorization request. +_redirectHTTPHandler = [[OIDRedirectHTTPHandler alloc] initWithSuccessURL:successURL]; +NSURL *redirectURI = [_redirectHTTPHandler startHTTPListener:nil]; +``` + +Then, initiate the authorization request. By using the +`authStateByPresentingAuthorizationRequest` convenience method, the token +exchange will be performed automatically, and everything will be protected with +PKCE (if the server supports it). By assigning the return value to the +`OIDRedirectHTTPHandler`'s `currentAuthorizationFlow`, the authorization will +continue automatically once the user makes their choice: + +```objc +// builds authentication request +OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration + clientId:kClientID + clientSecret:kClientSecret + scopes:@[ OIDScopeOpenID ] + redirectURL:redirectURI + responseType:OIDResponseTypeCode + additionalParameters:nil]; +// performs authentication request +__weak __typeof(self) weakSelf = self; +_redirectHTTPHandler.currentAuthorizationFlow = + [OIDAuthState authStateByPresentingAuthorizationRequest:request + callback:^(OIDAuthState *_Nullable authState, + NSError *_Nullable error) { + // Brings this app to the foreground. + [[NSRunningApplication currentApplication] + activateWithOptions:(NSApplicationActivateAllWindows | + NSApplicationActivateIgnoringOtherApps)]; + + // Processes the authorization response. + if (authState) { + NSLog(@"Got authorization tokens. Access token: %@", + authState.lastTokenResponse.accessToken); + } else { + NSLog(@"Authorization error: %@", error.localizedDescription); + } + [weakSelf setAuthState:authState]; +}]; +``` + +### Making API Calls + +AppAuth gives you the raw token information, if you need it. However, we +recommend that users of the `OIDAuthState` convenience wrapper use the provided +`performActionWithFreshTokens:` method to perform their API calls to avoid +needing to worry about token freshness: + +Objective-C +```objc +[_authState performActionWithFreshTokens:^(NSString *_Nonnull accessToken, + NSString *_Nonnull idToken, + NSError *_Nullable error) { + if (error) { + NSLog(@"Error fetching fresh tokens: %@", [error localizedDescription]); + return; + } + + // perform your API request using the tokens +}]; +``` + +Swift +```swift +let userinfoEndpoint = URL(string:"https://openidconnect.googleapis.com/v1/userinfo")! +self.authState?.performAction() { (accessToken, idToken, error) in + + if error != nil { + print("Error fetching fresh tokens: \(error?.localizedDescription ?? "Unknown error")") + return + } + guard let accessToken = accessToken else { + return + } + + // Add Bearer token to request + var urlRequest = URLRequest(url: userinfoEndpoint) + urlRequest.allHTTPHeaderFields = ["Authorization": "Bearer \(accessToken)"] + + // Perform request... +} +``` + +### Custom User-Agents + +Each OAuth flow involves presenting an external user-agent to the user, that +allows them to interact with the OAuth authorization server. Typical examples +of a user-agent are the user's browser, or an in-app browser tab incarnation +like `ASWebAuthenticationSession` on iOS. + +AppAuth ships with several implementations of an external user-agent out of the +box, including defaults for iOS and macOS suitable for most cases. The default +user-agents typically share persistent cookies with the system default browser, +to improve the chance that the user doesn't need to sign-in all over again. + +It is possible to change the user-agent that AppAuth uses, and even write your +own - all without needing to fork the library. + +All implementations of the external user-agent, be they included or created by +you need to conform to the +[`OIDExternalUserAgent`](http://openid.github.io/AppAuth-iOS/docs/latest/protocol_o_i_d_external_user_agent-p.html) +protocol. + +Instances of the `OIDExternalUserAgent`are passed into +[`OIDAuthState.authStateByPresentingAuthorizationRequest:externalUserAgent:callback`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_auth_state.html#ac762fe2bf95c116f0b437419be211fa1) +and/or +[`OIDAuthorizationService.presentAuthorizationRequest:externalUserAgent:callback:`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_authorization_service.html#ae551f8e6887366a46e49b09b37389b8f) +rather than using the platform-specific convenience methods (which use the +default user-agents for their respective platforms), like +[`OIDAuthState.authStateByPresentingAuthorizationRequest:presentingViewController:callback:`](http://openid.github.io/AppAuth-iOS/docs/latest/category_o_i_d_auth_state_07_i_o_s_08.html#ae32fd0732cd3192cd5219f2655a4c85c). + +Popular use-cases for writing your own user-agent implementation include needing +to style the user-agent in ways not supported by AppAuth, and implementing a +fully custom flow with your own business logic. You can take one of the existing +implementations as a starting point to copy, rename, and customize to your +needs. + +#### Custom Browser User-Agent + +AppAuth for iOS includes a few extra user-agent implementations which you can +try, or use as a reference for your own implementation. One of them, +[`OIDExternalUserAgentIOSCustomBrowser`](http://openid.github.io/AppAuth-iOS/docs/latest/interface_o_i_d_external_user_agent_i_o_s_custom_browser.html) +enables you to use a different browser for authentication, like Chrome for iOS +or Firefox for iOS. + +Here's how to configure AppAuth to use a custom browser using the +`OIDExternalUserAgentIOSCustomBrowser` user agent: + +First, add the following array to your +[Info.plist](https://github.com/openid/AppAuth-iOS/blob/135f99d2cb4e9d18d310ac2588b905e612461561/Examples/Example-iOS_ObjC/Source/Info.plist#L34) +(in XCode, right click -> Open As -> Source Code) + +``` + LSApplicationQueriesSchemes + + googlechromes + opera-https + firefox + +``` + +This is required so that AppAuth can test for the browser and open the app store +if it's not installed (the default behavior of this user-agent). You only need +to include the URL scheme of the actual browser you intend to use. + +Objective-C +```objc +// performs authentication request +AppDelegate *appDelegate = + (AppDelegate *)[UIApplication sharedApplication].delegate; +id userAgent = + [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome]; +appDelegate.currentAuthorizationFlow = + [OIDAuthState authStateByPresentingAuthorizationRequest:request + externalUserAgent:self + callback:^(OIDAuthState *_Nullable authState, + NSError *_Nullable error) { + if (authState) { + NSLog(@"Got authorization tokens. Access token: %@", + authState.lastTokenResponse.accessToken); + [self setAuthState:authState]; + } else { + NSLog(@"Authorization error: %@", [error localizedDescription]); + [self setAuthState:nil]; + } +}]; +``` + +That's it! With those two changes (which you can try on the included sample), +AppAuth will use Chrome iOS for the authorization request (and open Chrome in +the App Store if it's not installed). + +⚠️**Note: the `OIDExternalUserAgentIOSCustomBrowser` user-agent is not intended for consumer apps**. It is designed for +advanced enterprise use-cases where the app developers have greater control over +the operating environment and have special requirements that require a custom +browser like Chrome. + +You don't need to stop with the included external user agents either! Since the +[`OIDExternalUserAgent`](http://openid.github.io/AppAuth-iOS/docs/latest/protocol_o_i_d_external_user_agent-p.html) +protocol is part of AppAuth's public API, you can implement your own versions of +it. In the above example, +`userAgent = [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome]` would +be replaced with an instantiation of your user-agent implementation. + +## API Documentation + +Browse the [API documentation](http://openid.github.io/AppAuth-iOS/docs/latest/annotated.html). + +## Included Samples + +Sample apps that explore core AppAuth features are available for iOS and macOS; follow the instructions in [Examples/README.md](Examples/README.md) to get started. diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth.h new file mode 100644 index 00000000..4f779df3 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth.h @@ -0,0 +1,92 @@ +/*! @file AppAuth.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthState.h" +#import "OIDAuthStateChangeDelegate.h" +#import "OIDAuthStateErrorDelegate.h" +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDAuthorizationService.h" +#import "OIDError.h" +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" +#import "OIDExternalUserAgentRequest.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDGrantTypes.h" +#import "OIDIDToken.h" +#import "OIDRegistrationRequest.h" +#import "OIDRegistrationResponse.h" +#import "OIDResponseTypes.h" +#import "OIDScopes.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDTokenUtilities.h" +#import "OIDURLSessionProvider.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" + +#if TARGET_OS_TV +#elif TARGET_OS_WATCH +#elif TARGET_OS_IOS || TARGET_OS_MACCATALYST +#import "OIDAuthState+IOS.h" +#import "OIDAuthorizationService+IOS.h" +#import "OIDExternalUserAgentIOS.h" +#import "OIDExternalUserAgentIOSCustomBrowser.h" +#import "OIDExternalUserAgentCatalyst.h" +#elif TARGET_OS_MAC +#import "OIDAuthState+Mac.h" +#import "OIDAuthorizationService+Mac.h" +#import "OIDExternalUserAgentMac.h" +#import "OIDRedirectHTTPHandler.h" +#else +#error "Platform Undefined" +#endif + +/*! @mainpage AppAuth for iOS and macOS + + @section introduction Introduction + + AppAuth for iOS and macOS is a client SDK for communicating with [OAuth 2.0] + (https://tools.ietf.org/html/rfc6749) and [OpenID Connect] + (http://openid.net/specs/openid-connect-core-1_0.html) providers. It strives to + directly map the requests and responses of those specifications, while following + the idiomatic style of the implementation language. In addition to mapping the + raw protocol flows, convenience methods are available to assist with common + tasks like performing an action with fresh tokens. + + It follows the best practices set out in + [RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252) + including using `SFAuthenticationSession` and `SFSafariViewController` on iOS + for the auth request. Web view and `WKWebView` are explicitly *not* + supported due to the security and usability reasons explained in + [Section 8.12 of RFC 8252](https://tools.ietf.org/html/rfc8252#section-8.12). + + It also supports the [PKCE](https://tools.ietf.org/html/rfc7636) extension to + OAuth which was created to secure authorization codes in public clients when + custom URI scheme redirects are used. The library is friendly to other + extensions (standard or otherwise) with the ability to handle additional params + in all protocol requests and responses. + + Homepage: http://openid.github.io/AppAuth-iOS/
+ API Documentation: http://openid.github.io/AppAuth-iOS/docs/latest
+ Git Repository: https://github.com/openid/AppAuth-iOS
+ + */ diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.h new file mode 100644 index 00000000..99ca4573 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.h @@ -0,0 +1,63 @@ +/*! @file OIDAuthState+IOS.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import + +#import "OIDAuthState.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief iOS specific convenience methods for @c OIDAuthState. + */ +@interface OIDAuthState (IOS) + +/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request + and performing the authorization code exchange in the case of code flow requests. For + the hybrid flow, the caller should validate the id_token and c_hash, then perform the token + request (@c OIDAuthorizationService.performTokenRequest:callback:) + and update the OIDAuthState with the results (@c + OIDAuthState.updateWithTokenResponse:error:). + @param authorizationRequest The authorization request to present. + @param presentingViewController The view controller from which to present the + @c SFSafariViewController. On iOS 13, the window of this UIViewController + is used as the ASPresentationAnchor. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + */ ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDAuthStateAuthorizationCallback)callback; + ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + callback:(OIDAuthStateAuthorizationCallback)callback API_AVAILABLE(ios(11)) API_UNAVAILABLE(macCatalyst) + __deprecated_msg("This method will not work on iOS 13. Use " + "authStateByPresentingAuthorizationRequest:presentingViewController:callback:"); + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.m new file mode 100644 index 00000000..9f3a4e8c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthState+IOS.m @@ -0,0 +1,58 @@ +/*! @file OIDAuthState+IOS.m + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import "OIDAuthState+IOS.h" +#import "OIDExternalUserAgentIOS.h" +#import "OIDExternalUserAgentCatalyst.h" + +@implementation OIDAuthState (IOS) + ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDAuthStateAuthorizationCallback)callback { + id externalUserAgent; +#if TARGET_OS_MACCATALYST + externalUserAgent = [[OIDExternalUserAgentCatalyst alloc] + initWithPresentingViewController:presentingViewController]; +#else // TARGET_OS_MACCATALYST + externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController:presentingViewController]; +#endif // TARGET_OS_MACCATALYST + return [self authStateByPresentingAuthorizationRequest:authorizationRequest + externalUserAgent:externalUserAgent + callback:callback]; +} + +#if !TARGET_OS_MACCATALYST ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + callback:(OIDAuthStateAuthorizationCallback)callback { + OIDExternalUserAgentIOS *externalUserAgent = [[OIDExternalUserAgentIOS alloc] init]; + return [self authStateByPresentingAuthorizationRequest:authorizationRequest + externalUserAgent:externalUserAgent + callback:callback]; +} +#endif // !TARGET_OS_MACCATALYST + +@end + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.h new file mode 100644 index 00000000..c6e14f19 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.h @@ -0,0 +1,50 @@ +/*! @file OIDAuthorizationService+IOS.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import + +#import "OIDAuthorizationService.h" +#import "OIDExternalUserAgentSession.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Provides iOS specific authorization request handling. + */ +@interface OIDAuthorizationService (IOS) + +/*! @brief Perform an authorization flow using \SFSafariViewController. + @param request The authorization request. + @param presentingViewController The view controller from which to present the + \SFSafariViewController. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + */ ++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDAuthorizationCallback)callback; +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.m new file mode 100644 index 00000000..05ccff5d --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDAuthorizationService+IOS.m @@ -0,0 +1,48 @@ +/*! @file OIDAuthorizationService+IOS.m + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import "OIDAuthorizationService+IOS.h" +#import "OIDExternalUserAgentIOS.h" +#import "OIDExternalUserAgentCatalyst.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation OIDAuthorizationService (IOS) + ++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDAuthorizationCallback)callback { + id externalUserAgent; +#if TARGET_OS_MACCATALYST + externalUserAgent = [[OIDExternalUserAgentCatalyst alloc] + initWithPresentingViewController:presentingViewController]; +#else // TARGET_OS_MACCATALYST + externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController:presentingViewController]; +#endif // TARGET_OS_MACCATALYST + return [self presentAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.h new file mode 100644 index 00000000..d98d4413 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.h @@ -0,0 +1,52 @@ +/*! @file OIDExternalUserAgentCatalyst.h + @brief AppAuth iOS SDK + @copyright + Copyright 2019 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import + +#import "OIDExternalUserAgent.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief A Catalyst specific external user-agent that uses `ASWebAuthenticationSession` to + present the request. +*/ +API_AVAILABLE(macCatalyst(13)) API_UNAVAILABLE(ios) +@interface OIDExternalUserAgentCatalyst : NSObject + +/*! @internal + @brief Unavailable. Please use @c initWithPresentingViewController: + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +/*! @brief The designated initializer. + @param presentingViewController The view controller from which to present the + \SFSafariViewController. + */ +- (nullable instancetype)initWithPresentingViewController: + (UIViewController *)presentingViewController + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.m new file mode 100644 index 00000000..fc9cef5c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.m @@ -0,0 +1,145 @@ +/*! @file OIDExternalUserAgentCatalyst.m + @brief AppAuth iOS SDK + @copyright + Copyright 2019 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import "OIDExternalUserAgentCatalyst.h" + +#import +#import + +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDExternalUserAgentRequest.h" + +#if TARGET_OS_MACCATALYST + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDExternalUserAgentCatalyst () +@end + +@implementation OIDExternalUserAgentCatalyst { + UIViewController *_presentingViewController; + + BOOL _externalUserAgentFlowInProgress; + __weak id _session; + ASWebAuthenticationSession *_webAuthenticationVC; +} + +- (nullable instancetype)initWithPresentingViewController: + (UIViewController *)presentingViewController { + self = [super init]; + if (self) { + _presentingViewController = presentingViewController; + } + return self; +} + +- (BOOL)presentExternalUserAgentRequest:(id)request + session:(id)session { + if (_externalUserAgentFlowInProgress) { + // TODO: Handle errors as authorization is already in progress. + return NO; + } + + _externalUserAgentFlowInProgress = YES; + _session = session; + BOOL openedUserAgent = NO; + NSURL *requestURL = [request externalUserAgentRequestURL]; + + __weak OIDExternalUserAgentCatalyst *weakSelf = self; + NSString *redirectScheme = request.redirectScheme; + ASWebAuthenticationSession *authenticationVC = + [[ASWebAuthenticationSession alloc] initWithURL:requestURL + callbackURLScheme:redirectScheme + completionHandler:^(NSURL * _Nullable callbackURL, + NSError * _Nullable error) { + __strong OIDExternalUserAgentCatalyst *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + strongSelf->_webAuthenticationVC = nil; + if (callbackURL) { + [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL]; + } else { + NSError *safariError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:error + description:nil]; + [strongSelf->_session failExternalUserAgentFlowWithError:safariError]; + } + }]; + + authenticationVC.presentationContextProvider = self; + _webAuthenticationVC = authenticationVC; + openedUserAgent = [authenticationVC start]; + + if (!openedUserAgent) { + [self cleanUp]; + NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError + underlyingError:nil + description:@"Unable to open ASWebAuthenticationSession view controller."]; + [session failExternalUserAgentFlowWithError:safariError]; + } + return openedUserAgent; +} + +- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion { + if (!_externalUserAgentFlowInProgress) { + // Ignore this call if there is no authorization flow in progress. + if (completion) completion(); + return; + } + + ASWebAuthenticationSession *webAuthenticationVC = _webAuthenticationVC; + + [self cleanUp]; + + if (webAuthenticationVC) { + // dismiss the ASWebAuthenticationSession + [webAuthenticationVC cancel]; + if (completion) completion(); + } else { + if (completion) completion(); + } +} + +- (void)cleanUp { + // The weak reference to |_session| is set to nil to avoid accidentally using + // it while not in an authorization flow. + _webAuthenticationVC = nil; + _session = nil; + _externalUserAgentFlowInProgress = NO; +} + +#pragma mark - ASWebAuthenticationPresentationContextProviding + +- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session { + return _presentingViewController.view.window; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_MACCATALYST + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.h new file mode 100644 index 00000000..7261c050 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.h @@ -0,0 +1,53 @@ +/*! @file OIDExternalUserAgentIOS.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import + +#import "OIDExternalUserAgent.h" + +@class SFSafariViewController; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief An iOS specific external user-agent that uses the best possible user-agent available + depending on the version of iOS to present the request. + */ +API_UNAVAILABLE(macCatalyst) +@interface OIDExternalUserAgentIOS : NSObject + +- (nullable instancetype)init API_AVAILABLE(ios(11)) + __deprecated_msg("This method will not work on iOS 13, use " + "initWithPresentingViewController:presentingViewController"); + +/*! @brief The designated initializer. + @param presentingViewController The view controller from which to present the + \SFSafariViewController. + */ +- (nullable instancetype)initWithPresentingViewController: + (UIViewController *)presentingViewController + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m new file mode 100644 index 00000000..728f0868 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOS.m @@ -0,0 +1,256 @@ +/*! @file OIDExternalUserAgentIOS.m + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import "OIDExternalUserAgentIOS.h" + +#import +#import + +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDExternalUserAgentRequest.h" + +#if !TARGET_OS_MACCATALYST + +NS_ASSUME_NONNULL_BEGIN + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 +@interface OIDExternalUserAgentIOS () +@end +#else +@interface OIDExternalUserAgentIOS () +@end +#endif + +@implementation OIDExternalUserAgentIOS { + UIViewController *_presentingViewController; + + BOOL _externalUserAgentFlowInProgress; + __weak id _session; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" + __weak SFSafariViewController *_safariVC; + SFAuthenticationSession *_authenticationVC; + ASWebAuthenticationSession *_webAuthenticationVC; +#pragma clang diagnostic pop +} + +- (nullable instancetype)init { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + return [self initWithPresentingViewController:nil]; +#pragma clang diagnostic pop +} + +- (nullable instancetype)initWithPresentingViewController: + (UIViewController *)presentingViewController { + self = [super init]; + if (self) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + NSAssert(presentingViewController != nil, + @"presentingViewController cannot be nil on iOS 13"); +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + + _presentingViewController = presentingViewController; + } + return self; +} + +- (BOOL)presentExternalUserAgentRequest:(id)request + session:(id)session { + if (_externalUserAgentFlowInProgress) { + // TODO: Handle errors as authorization is already in progress. + return NO; + } + + _externalUserAgentFlowInProgress = YES; + _session = session; + BOOL openedUserAgent = NO; + NSURL *requestURL = [request externalUserAgentRequestURL]; + + // iOS 12 and later, use ASWebAuthenticationSession + if (@available(iOS 12.0, *)) { + // ASWebAuthenticationSession doesn't work with guided access (rdar://40809553) + if (!UIAccessibilityIsGuidedAccessEnabled()) { + __weak OIDExternalUserAgentIOS *weakSelf = self; + NSString *redirectScheme = request.redirectScheme; + ASWebAuthenticationSession *authenticationVC = + [[ASWebAuthenticationSession alloc] initWithURL:requestURL + callbackURLScheme:redirectScheme + completionHandler:^(NSURL * _Nullable callbackURL, + NSError * _Nullable error) { + __strong OIDExternalUserAgentIOS *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + strongSelf->_webAuthenticationVC = nil; + if (callbackURL) { + [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL]; + } else { + NSError *safariError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:error + description:nil]; + [strongSelf->_session failExternalUserAgentFlowWithError:safariError]; + } + }]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, *)) { + authenticationVC.presentationContextProvider = self; + } +#endif + _webAuthenticationVC = authenticationVC; + openedUserAgent = [authenticationVC start]; + } + } + // iOS 11, use SFAuthenticationSession + if (@available(iOS 11.0, *)) { + // SFAuthenticationSession doesn't work with guided access (rdar://40809553) + if (!openedUserAgent && !UIAccessibilityIsGuidedAccessEnabled()) { + __weak OIDExternalUserAgentIOS *weakSelf = self; + NSString *redirectScheme = request.redirectScheme; + SFAuthenticationSession *authenticationVC = + [[SFAuthenticationSession alloc] initWithURL:requestURL + callbackURLScheme:redirectScheme + completionHandler:^(NSURL * _Nullable callbackURL, + NSError * _Nullable error) { + __strong OIDExternalUserAgentIOS *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + strongSelf->_authenticationVC = nil; + if (callbackURL) { + [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL]; + } else { + NSError *safariError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:error + description:@"User cancelled."]; + [strongSelf->_session failExternalUserAgentFlowWithError:safariError]; + } + }]; + _authenticationVC = authenticationVC; + openedUserAgent = [authenticationVC start]; + } + } + // iOS 9 and 10, use SFSafariViewController + if (@available(iOS 9.0, *)) { + if (!openedUserAgent && _presentingViewController) { + SFSafariViewController *safariVC = + [[SFSafariViewController alloc] initWithURL:requestURL]; + safariVC.delegate = self; + _safariVC = safariVC; + [_presentingViewController presentViewController:safariVC animated:YES completion:nil]; + openedUserAgent = YES; + } + } + // iOS 8 and earlier, use mobile Safari + if (!openedUserAgent){ + openedUserAgent = [[UIApplication sharedApplication] openURL:requestURL]; + } + + if (!openedUserAgent) { + [self cleanUp]; + NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError + underlyingError:nil + description:@"Unable to open Safari."]; + [session failExternalUserAgentFlowWithError:safariError]; + } + return openedUserAgent; +} + +- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion { + if (!_externalUserAgentFlowInProgress) { + // Ignore this call if there is no authorization flow in progress. + if (completion) completion(); + return; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" + SFSafariViewController *safariVC = _safariVC; + SFAuthenticationSession *authenticationVC = _authenticationVC; + ASWebAuthenticationSession *webAuthenticationVC = _webAuthenticationVC; +#pragma clang diagnostic pop + + [self cleanUp]; + + if (webAuthenticationVC) { + // dismiss the ASWebAuthenticationSession + [webAuthenticationVC cancel]; + if (completion) completion(); + } else if (authenticationVC) { + // dismiss the SFAuthenticationSession + [authenticationVC cancel]; + if (completion) completion(); + } else if (safariVC) { + // dismiss the SFSafariViewController + [safariVC dismissViewControllerAnimated:YES completion:completion]; + } else { + if (completion) completion(); + } +} + +- (void)cleanUp { + // The weak references to |_safariVC| and |_session| are set to nil to avoid accidentally using + // them while not in an authorization flow. + _safariVC = nil; + _authenticationVC = nil; + _webAuthenticationVC = nil; + _session = nil; + _externalUserAgentFlowInProgress = NO; +} + +#pragma mark - SFSafariViewControllerDelegate + +- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller NS_AVAILABLE_IOS(9.0) { + if (controller != _safariVC) { + // Ignore this call if the safari view controller do not match. + return; + } + if (!_externalUserAgentFlowInProgress) { + // Ignore this call if there is no authorization flow in progress. + return; + } + id session = _session; + [self cleanUp]; + NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:nil + description:@"No external user agent flow in progress."]; + [session failExternalUserAgentFlowWithError:error]; +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 +#pragma mark - ASWebAuthenticationPresentationContextProviding + +- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){ + return _presentingViewController.view.window; +} +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + +@end + +NS_ASSUME_NONNULL_END + +#endif // !TARGET_OS_MACCATALYST + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.h new file mode 100644 index 00000000..2032e8c9 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.h @@ -0,0 +1,113 @@ +/*! @file OIDExternalUserAgentIOSCustomBrowser.h + @brief AppAuth iOS SDK + @copyright + Copyright 2018 Google LLC + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import + +#import "OIDExternalUserAgent.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief A block that transforms a regular http/https URL into one that will open in an + alternative browser. + @param requestURL the http/https request URL to be transformed. + @return transformed URL. + */ +typedef NSURL *_Nullable (^OIDCustomBrowserURLTransformation)(NSURL *_Nullable requestURL); + +/*! @brief An implementation of the OIDExternalUserAgent protocol for iOS that uses + a custom browser (i.e. not Safari) for external requests. It is suitable for browsers that + offer a custom url scheme that simply replaces the "https" scheme. It is not designed + for browsers that require other modifications to the URL. If the browser is not installed + the user will be prompted to install it. + */ +API_UNAVAILABLE(macCatalyst) +@interface OIDExternalUserAgentIOSCustomBrowser : NSObject + +/*! @brief URL transformation block for the browser. + */ +@property(nonatomic, readonly) OIDCustomBrowserURLTransformation URLTransformation; + +/*! @brief URL Scheme used to test for whether the browser is installed. + */ +@property(nonatomic, readonly, nullable) NSString *canOpenURLScheme; + +/*! @brief URL of the browser's App Store listing. + */ +@property(nonatomic, readonly, nullable) NSURL *appStoreURL; + +/*! @brief An instance of @c OIDExternalUserAgentIOSCustomBrowser for Chrome. + */ ++ (instancetype)CustomBrowserChrome; + +/*! @brief An instance of @c OIDExternalUserAgentIOSCustomBrowser for Firefox. + */ ++ (instancetype)CustomBrowserFirefox; + +/*! @brief An instance of @c OIDExternalUserAgentIOSCustomBrowser for Opera. + */ ++ (instancetype)CustomBrowserOpera; + +/*! @brief An instance of @c OIDExternalUserAgentIOSCustomBrowser for Safari. + */ ++ (instancetype)CustomBrowserSafari; + +/*! @brief Creates a @c OIDCustomBrowserURLTransformation using the scheme substitution method used + iOS browsers like Chrome and Firefox. + */ ++ (OIDCustomBrowserURLTransformation) + URLTransformationSchemeSubstitutionHTTPS:(NSString *)browserSchemeHTTPS + HTTP:(nullable NSString *)browserSchemeHTTP; + +/*! @brief Creates a @c OIDCustomBrowserURLTransformation with the URL prefix method used by + iOS browsers like Firefox. + */ ++ (OIDCustomBrowserURLTransformation) URLTransformationSchemeConcatPrefix:(NSString*)URLprefix; + +/*! @internal + @brief Unavailable. Please use @c initWithURLTransformation:canOpenURLScheme:appStoreURL: + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +/*! @brief OIDExternalUserAgent for a custom browser. @c presentExternalUserAgentRequest:session method + will return NO if the browser isn't installed. + */ +- (nullable instancetype)initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation; + +/*! @brief The designated initializer. + @param URLTransformation the transformation block to translate the URL into one that will open + in the desired custom browser. + @param canOpenURLScheme any scheme supported by the browser used to check if the browser is + installed. + @param appStoreURL URL of the browser in the app store. When this and @c canOpenURLScheme + are non-nil, @c presentExternalUserAgentRequest:session will redirect the user to the app store + if the browser is not installed. + */ +- (nullable instancetype)initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation + canOpenURLScheme:(nullable NSString *)canOpenURLScheme + appStoreURL:(nullable NSURL *)appStoreURL + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.m new file mode 100644 index 00000000..51d2e56c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.m @@ -0,0 +1,171 @@ +/*! @file OIDExternalUserAgentIOSCustomBrowser.m + @brief AppAuth iOS SDK + @copyright + Copyright 2018 Google LLC + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_MACCATALYST + +#import "OIDExternalUserAgentIOSCustomBrowser.h" + +#import + +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationService.h" +#import "OIDErrorUtilities.h" +#import "OIDURLQueryComponent.h" + +#if !TARGET_OS_MACCATALYST + +NS_ASSUME_NONNULL_BEGIN + +@implementation OIDExternalUserAgentIOSCustomBrowser + ++ (instancetype)CustomBrowserChrome { + // Chrome iOS documentation: https://developer.chrome.com/multidevice/ios/links + OIDCustomBrowserURLTransformation transform = [[self class] URLTransformationSchemeSubstitutionHTTPS:@"googlechromes" HTTP:@"googlechrome"]; + NSURL *appStoreURL = + [NSURL URLWithString:@"itms-apps://itunes.apple.com/us/app/chrome/id535886823"]; + return [[[self class] alloc] initWithURLTransformation:transform + canOpenURLScheme:@"googlechromes" + appStoreURL:appStoreURL]; +} + ++ (instancetype)CustomBrowserFirefox { + // Firefox iOS documentation: https://github.com/mozilla-mobile/firefox-ios-open-in-client + OIDCustomBrowserURLTransformation transform = + [[self class] URLTransformationSchemeConcatPrefix:@"firefox://open-url?url="]; + NSURL *appStoreURL = + [NSURL URLWithString:@"itms-apps://itunes.apple.com/us/app/firefox-web-browser/id989804926"]; + return [[[self class] alloc] initWithURLTransformation:transform + canOpenURLScheme:@"firefox" + appStoreURL:appStoreURL]; +} + ++ (instancetype)CustomBrowserOpera { + OIDCustomBrowserURLTransformation transform = + [[self class] URLTransformationSchemeSubstitutionHTTPS:@"opera-https" HTTP:@"opera-http"]; + NSURL *appStoreURL = + [NSURL URLWithString:@"itms-apps://itunes.apple.com/us/app/opera-mini-web-browser/id363729560"]; + return [[[self class] alloc] initWithURLTransformation:transform + canOpenURLScheme:@"opera-https" + appStoreURL:appStoreURL]; +} + ++ (instancetype)CustomBrowserSafari { + OIDCustomBrowserURLTransformation transformNOP = ^NSURL *(NSURL *requestURL) { + return requestURL; + }; + OIDExternalUserAgentIOSCustomBrowser *transform = + [[[self class] alloc] initWithURLTransformation:transformNOP]; + return transform; +} + ++ (OIDCustomBrowserURLTransformation) + URLTransformationSchemeSubstitutionHTTPS:(NSString *)browserSchemeHTTPS + HTTP:(nullable NSString *)browserSchemeHTTP { + OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) { + // Replace the URL Scheme with the Chrome equivalent. + NSString *newScheme = nil; + if ([requestURL.scheme isEqualToString:@"https"]) { + newScheme = browserSchemeHTTPS; + } else if ([requestURL.scheme isEqualToString:@"http"]) { + if (!browserSchemeHTTP) { + NSAssert(false, @"No HTTP scheme registered for browser"); + return nil; + } + newScheme = browserSchemeHTTP; + } + + // Replaces the URI scheme with the custom scheme + NSURLComponents *components = [NSURLComponents componentsWithURL:requestURL + resolvingAgainstBaseURL:YES]; + components.scheme = newScheme; + return components.URL; + }; + return transform; +} + ++ (OIDCustomBrowserURLTransformation)URLTransformationSchemeConcatPrefix:(NSString *)URLprefix { + OIDCustomBrowserURLTransformation transform = ^NSURL *(NSURL *requestURL) { + NSString *requestURLString = [requestURL absoluteString]; + NSMutableCharacterSet *allowedParamCharacters = + [OIDURLQueryComponent URLParamValueAllowedCharacters]; + NSString *encodedUrl = [requestURLString stringByAddingPercentEncodingWithAllowedCharacters:allowedParamCharacters]; + NSString *newURL = [NSString stringWithFormat:@"%@%@", URLprefix, encodedUrl]; + return [NSURL URLWithString:newURL]; + }; + return transform; +} + +- (nullable instancetype)initWithURLTransformation: + (OIDCustomBrowserURLTransformation)URLTransformation { + return [self initWithURLTransformation:URLTransformation canOpenURLScheme:nil appStoreURL:nil]; +} + +- (nullable instancetype) + initWithURLTransformation:(OIDCustomBrowserURLTransformation)URLTransformation + canOpenURLScheme:(nullable NSString *)canOpenURLScheme + appStoreURL:(nullable NSURL *)appStoreURL { + self = [super init]; + if (self) { + _URLTransformation = URLTransformation; + _canOpenURLScheme = canOpenURLScheme; + _appStoreURL = appStoreURL; + } + return self; +} + +- (BOOL)presentExternalUserAgentRequest:(nonnull id)request + session:(nonnull id)session { + // If the app store URL is set, checks if the app is installed and if not opens the app store. + if (_appStoreURL && _canOpenURLScheme) { + // Verifies existence of LSApplicationQueriesSchemes Info.plist key. + NSArray __unused* canOpenURLs = + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LSApplicationQueriesSchemes"]; + NSAssert(canOpenURLs, @"plist missing LSApplicationQueriesSchemes key"); + NSAssert1([canOpenURLs containsObject:_canOpenURLScheme], + @"plist missing LSApplicationQueriesSchemes entry for '%@'", _canOpenURLScheme); + + // Opens AppStore if app isn't installed + NSString *testURLString = [NSString stringWithFormat:@"%@://example.com", _canOpenURLScheme]; + NSURL *testURL = [NSURL URLWithString:testURLString]; + if (![[UIApplication sharedApplication] canOpenURL:testURL]) { + [[UIApplication sharedApplication] openURL:_appStoreURL]; + return NO; + } + } + + // Transforms the request URL and opens it. + NSURL *requestURL = [request externalUserAgentRequestURL]; + requestURL = _URLTransformation(requestURL); + BOOL openedInBrowser = [[UIApplication sharedApplication] openURL:requestURL]; + return openedInBrowser; +} + +- (void)dismissExternalUserAgentAnimated:(BOOL)animated + completion:(nonnull void (^)(void))completion { + completion(); +} + +@end + +NS_ASSUME_NONNULL_END + +#endif // !TARGET_OS_MACCATALYST + +#endif // TARGET_OS_IOS || TARGET_OS_MACCATALYST diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore.h new file mode 100644 index 00000000..c30af464 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore.h @@ -0,0 +1,44 @@ +/*! @file AppAuthCore.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthState.h" +#import "OIDAuthStateChangeDelegate.h" +#import "OIDAuthStateErrorDelegate.h" +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDAuthorizationService.h" +#import "OIDError.h" +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" +#import "OIDExternalUserAgentRequest.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDGrantTypes.h" +#import "OIDIDToken.h" +#import "OIDRegistrationRequest.h" +#import "OIDRegistrationResponse.h" +#import "OIDResponseTypes.h" +#import "OIDScopes.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDTokenUtilities.h" +#import "OIDURLSessionProvider.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.h new file mode 100644 index 00000000..68697d2c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.h @@ -0,0 +1,272 @@ +/*! @file OIDAuthState.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +#import + +@class OIDAuthorizationRequest; +@class OIDAuthorizationResponse; +@class OIDAuthState; +@class OIDRegistrationResponse; +@class OIDTokenResponse; +@class OIDTokenRequest; +@protocol OIDAuthStateChangeDelegate; +@protocol OIDAuthStateErrorDelegate; +@protocol OIDExternalUserAgent; +@protocol OIDExternalUserAgentSession; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents a block used to call an action with a fresh access token. + @param accessToken A valid access token if available. + @param idToken A valid ID token if available. + @param error The error if an error occurred. + */ +typedef void (^OIDAuthStateAction)(NSString *_Nullable accessToken, + NSString *_Nullable idToken, + NSError *_Nullable error); + +/*! @brief The method called when the @c + OIDAuthState.authStateByPresentingAuthorizationRequest:presentingViewController:callback: + method has completed or failed. + @param authState The auth state, if the authorization request succeeded. + @param error The error if an error occurred. + */ +typedef void (^OIDAuthStateAuthorizationCallback)(OIDAuthState *_Nullable authState, + NSError *_Nullable error); + +/*! @brief A convenience class that retains the auth state between @c OIDAuthorizationResponse%s + and @c OIDTokenResponse%s. + */ +@interface OIDAuthState : NSObject + +/*! @brief The most recent refresh token received from the server. + @discussion Rather than using this property directly, you should call + @c OIDAuthState.performActionWithFreshTokens:. + @remarks refresh_token + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *refreshToken; + +/*! @brief The scope of the current authorization grant. + @discussion This represents the latest scope returned by the server and may be a subset of the + scope that was initially granted. + @remarks scope + */ +@property(nonatomic, readonly, nullable) NSString *scope; + +/*! @brief The most recent authorization response used to update the authorization state. For the + implicit flow, this will contain the latest access token. + */ +@property(nonatomic, readonly) OIDAuthorizationResponse *lastAuthorizationResponse; + +/*! @brief The most recent token response used to update this authorization state. This will + contain the latest access token. + */ +@property(nonatomic, readonly, nullable) OIDTokenResponse *lastTokenResponse; + +/*! @brief The most recent registration response used to update this authorization state. This will + contain the latest client credentials. + */ +@property(nonatomic, readonly, nullable) OIDRegistrationResponse *lastRegistrationResponse; + +/*! @brief The authorization error that invalidated this @c OIDAuthState. + @discussion The authorization error encountered by @c OIDAuthState or set by the user via + @c OIDAuthState.updateWithAuthorizationError: that invalidated this @c OIDAuthState. + Authorization errors from @c OIDAuthState will always have a domain of + @c ::OIDOAuthAuthorizationErrorDomain or @c ::OIDOAuthTokenErrorDomain. Note: that after + unarchiving the @c OIDAuthState object, the \NSError_userInfo property of this error will + be nil. + */ +@property(nonatomic, readonly, nullable) NSError *authorizationError; + +/*! @brief Returns YES if the authorization state is not known to be invalid. + @discussion Returns YES if no OAuth errors have been received, and the last call resulted in a + successful access token or id token. This does not mean that the access is fresh - just + that it was valid the last time it was used. Note that network and other transient errors + do not invalidate the authorized state. If NO, you should authenticate the user again, + using a fresh authorization request. Invalid @c OIDAuthState objects may still be useful in + that case, to hint at the previously authorized user and streamline the re-authentication + experience. + */ +@property(nonatomic, readonly) BOOL isAuthorized; + +/*! @brief The @c OIDAuthStateChangeDelegate delegate. + @discussion Use the delegate to observe state changes (and update storage) as well as error + states. + */ +@property(nonatomic, weak, nullable) id stateChangeDelegate; + +/*! @brief The @c OIDAuthStateErrorDelegate delegate. + @discussion Use the delegate to observe state changes (and update storage) as well as error + states. + */ +@property(nonatomic, weak, nullable) id errorDelegate; + +/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request + and performing the authorization code exchange in the case of code flow requests. For + the hybrid flow, the caller should validate the id_token and c_hash, then perform the token + request (@c OIDAuthorizationService.performTokenRequest:callback:) + and update the OIDAuthState with the results (@c + OIDAuthState.updateWithTokenResponse:error:). + @param authorizationRequest The authorization request to present. + @param externalUserAgent A external user agent that can present an external user-agent request. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + */ ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + externalUserAgent:(id)externalUserAgent + callback:(OIDAuthStateAuthorizationCallback)callback; + +/*! @internal + @brief Unavailable. Please use @c initWithAuthorizationResponse:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Creates an auth state from an authorization response. + @param authorizationResponse The authorization response. + */ +- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse; + +/*! @brief Creates an auth state from an authorization and token response. + @param authorizationResponse The authorization response. + @param tokenResponse The token response. + */ +- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse + tokenResponse:(nullable OIDTokenResponse *)tokenResponse; + +/*! @brief Creates an auth state from an registration response. + @param registrationResponse The registration response. + */ +- (instancetype)initWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse; + +/*! @brief Creates an auth state from an authorization, token and registration response. + @param authorizationResponse The authorization response. + @param tokenResponse The token response. + @param registrationResponse The registration response. + */ +- (instancetype)initWithAuthorizationResponse: + (nullable OIDAuthorizationResponse *)authorizationResponse + tokenResponse:(nullable OIDTokenResponse *)tokenResponse + registrationResponse:(nullable OIDRegistrationResponse *)registrationResponse + NS_DESIGNATED_INITIALIZER; + +/*! @brief Updates the authorization state based on a new authorization response. + @param authorizationResponse The new authorization response to update the state with. + @param error Any error encountered when performing the authorization request. Errors in the + domain @c ::OIDOAuthAuthorizationErrorDomain are reflected in the auth state, other errors + are assumed to be transient, and ignored. + @discussion Typically called with the response from an incremental authorization request, + or if using the implicit flow. Will clear the @c #lastTokenResponse property. + */ +- (void)updateWithAuthorizationResponse:(nullable OIDAuthorizationResponse *)authorizationResponse + error:(nullable NSError *)error; + +/*! @brief Updates the authorization state based on a new token response. + @param tokenResponse The new token response to update the state from. + @param error Any error encountered when performing the authorization request. Errors in the + domain @c ::OIDOAuthTokenErrorDomain are reflected in the auth state, other errors + are assumed to be transient, and ignored. + @discussion Typically called with the response from an authorization code exchange, or a token + refresh. + */ +- (void)updateWithTokenResponse:(nullable OIDTokenResponse *)tokenResponse + error:(nullable NSError *)error; + +/*! @brief Updates the authorization state based on a new registration response. + @param registrationResponse The new registration response to update the state with. + @discussion Typically called with the response from a successful client registration + request. Will reset the auth state. + */ +- (void)updateWithRegistrationResponse:(nullable OIDRegistrationResponse *)registrationResponse; + +/*! @brief Updates the authorization state based on an authorization error. + @param authorizationError The authorization error. + @discussion Call this method if you receive an authorization error during an API call to + invalidate the authentication state of this @c OIDAuthState. Don't call with errors + unrelated to authorization, such as transient network errors. + The OIDAuthStateErrorDelegate.authState:didEncounterAuthorizationError: method of + @c #errorDelegate will be called with the error. + You may optionally use the convenience method + OIDErrorUtilities.resourceServerAuthorizationErrorWithCode:errorResponse:underlyingError: + to create \NSError objects for use here. + The latest error received is stored in @c #authorizationError. Note: that after unarchiving + this object, the \NSError_userInfo property of this error will be nil. + */ +- (void)updateWithAuthorizationError:(NSError *)authorizationError; + +/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a + refresh was needed and failed, with the error that caused it to fail. + @param action The block to execute with a fresh token. This block will be executed on the main + thread. + */ +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action; + +/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a + refresh was needed and failed, with the error that caused it to fail. + @param action The block to execute with a fresh token. This block will be executed on the main + thread. + @param additionalParameters Additional parameters for the token request if token is + refreshed. + */ +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters: + (nullable NSDictionary *)additionalParameters; + +/*! @brief Calls the block with a valid access token (refreshing it first, if needed), or if a + refresh was needed and failed, with the error that caused it to fail. + @param action The block to execute with a fresh token. This block will be executed on the main + thread. + @param additionalParameters Additional parameters for the token request if token is + refreshed. + @param dispatchQueue The dispatchQueue on which to dispatch the action block. + */ +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters: + (nullable NSDictionary *)additionalParameters + dispatchQueue:(dispatch_queue_t)dispatchQueue; + +/*! @brief Forces a token refresh the next time @c OIDAuthState.performActionWithFreshTokens: is + called, even if the current tokens are considered valid. + */ +- (void)setNeedsTokenRefresh; + +/*! @brief Creates a token request suitable for refreshing an access token. + @return A @c OIDTokenRequest suitable for using a refresh token to obtain a new access token. + @discussion After performing the refresh, call @c OIDAuthState.updateWithTokenResponse:error: + to update the authorization state based on the response. Rather than doing the token refresh + yourself, you should use @c OIDAuthState.performActionWithFreshTokens:. + @see https://tools.ietf.org/html/rfc6749#section-1.5 + */ +- (nullable OIDTokenRequest *)tokenRefreshRequest; + +/*! @brief Creates a token request suitable for refreshing an access token. + @param additionalParameters Additional parameters for the token request. + @return A @c OIDTokenRequest suitable for using a refresh token to obtain a new access token. + @discussion After performing the refresh, call @c OIDAuthState.updateWithTokenResponse:error: + to update the authorization state based on the response. Rather than doing the token refresh + yourself, you should use @c OIDAuthState.performActionWithFreshTokens:. + @see https://tools.ietf.org/html/rfc6749#section-1.5 + */ +- (nullable OIDTokenRequest *)tokenRefreshRequestWithAdditionalParameters: + (nullable NSDictionary *)additionalParameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.m new file mode 100644 index 00000000..fe8a1622 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthState.m @@ -0,0 +1,570 @@ +/*! @file OIDAuthState.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthState.h" + +#import "OIDAuthStateChangeDelegate.h" +#import "OIDAuthStateErrorDelegate.h" +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDAuthorizationService.h" +#import "OIDDefines.h" +#import "OIDError.h" +#import "OIDErrorUtilities.h" +#import "OIDRegistrationResponse.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDTokenUtilities.h" + +/*! @brief Key used to encode the @c refreshToken property for @c NSSecureCoding. + */ +static NSString *const kRefreshTokenKey = @"refreshToken"; + +/*! @brief Key used to encode the @c needsTokenRefresh property for @c NSSecureCoding. + */ +static NSString *const kNeedsTokenRefreshKey = @"needsTokenRefresh"; + +/*! @brief Key used to encode the @c scope property for @c NSSecureCoding. + */ +static NSString *const kScopeKey = @"scope"; + +/*! @brief Key used to encode the @c lastAuthorizationResponse property for @c NSSecureCoding. + */ +static NSString *const kLastAuthorizationResponseKey = @"lastAuthorizationResponse"; + +/*! @brief Key used to encode the @c lastTokenResponse property for @c NSSecureCoding. + */ +static NSString *const kLastTokenResponseKey = @"lastTokenResponse"; + +/*! @brief Key used to encode the @c lastOAuthError property for @c NSSecureCoding. + */ +static NSString *const kAuthorizationErrorKey = @"authorizationError"; + +/*! @brief The exception thrown when a developer tries to create a refresh request from an + authorization request with no authorization code. + */ +static NSString *const kRefreshTokenRequestException = + @"Attempted to create a token refresh request from a token response with no refresh token."; + +/*! @brief Number of seconds the access token is refreshed before it actually expires. + */ +static const NSUInteger kExpiryTimeTolerance = 60; + +/*! @brief Object to hold OIDAuthState pending actions. + */ +@interface OIDAuthStatePendingAction : NSObject +@property(nonatomic, readonly, nullable) OIDAuthStateAction action; +@property(nonatomic, readonly, nullable) dispatch_queue_t dispatchQueue; +@end +@implementation OIDAuthStatePendingAction +- (id)initWithAction:(OIDAuthStateAction)action andDispatchQueue:(dispatch_queue_t)dispatchQueue { + self = [super init]; + if (self) { + _action = action; + _dispatchQueue = dispatchQueue; + } + return self; +} +@end + +@interface OIDAuthState () + +/*! @brief The access token generated by the authorization server. + @discussion Rather than using this property directly, you should call + @c OIDAuthState.withFreshTokenPerformAction:. + */ +@property(nonatomic, readonly, nullable) NSString *accessToken; + +/*! @brief The approximate expiration date & time of the access token. + @discussion Rather than using this property directly, you should call + @c OIDAuthState.withFreshTokenPerformAction:. + */ +@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate; + +/*! @brief ID Token value associated with the authenticated session. + @discussion Rather than using this property directly, you should call + OIDAuthState.withFreshTokenPerformAction:. + */ +@property(nonatomic, readonly, nullable) NSString *idToken; + +/*! @brief Private method, called when the internal state changes. + */ +- (void)didChangeState; + +@end + + +@implementation OIDAuthState { + /*! @brief Array of pending actions (use @c _pendingActionsSyncObject to synchronize access). + */ + NSMutableArray *_pendingActions; + + /*! @brief Object for synchronizing access to @c pendingActions. + */ + id _pendingActionsSyncObject; + + /*! @brief If YES, tokens will be refreshed on the next API call regardless of expiry. + */ + BOOL _needsTokenRefresh; +} + +#pragma mark - Convenience initializers + ++ (id) + authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest + externalUserAgent:(id)externalUserAgent + callback:(OIDAuthStateAuthorizationCallback)callback { + // presents the authorization request + id authFlowSession = [OIDAuthorizationService + presentAuthorizationRequest:authorizationRequest + externalUserAgent:externalUserAgent + callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, + NSError *_Nullable authorizationError) { + // inspects response and processes further if needed (e.g. authorization + // code exchange) + if (authorizationResponse) { + if ([authorizationRequest.responseType + isEqualToString:OIDResponseTypeCode]) { + // if the request is for the code flow (NB. not hybrid), assumes the + // code is intended for this client, and performs the authorization + // code exchange + OIDTokenRequest *tokenExchangeRequest = + [authorizationResponse tokenExchangeRequest]; + [OIDAuthorizationService performTokenRequest:tokenExchangeRequest + originalAuthorizationResponse:authorizationResponse + callback:^(OIDTokenResponse *_Nullable tokenResponse, + NSError *_Nullable tokenError) { + OIDAuthState *authState; + if (tokenResponse) { + authState = [[OIDAuthState alloc] + initWithAuthorizationResponse: + authorizationResponse + tokenResponse:tokenResponse]; + } + callback(authState, tokenError); + }]; + } else { + // hybrid flow (code id_token). Two possible cases: + // 1. The code is not for this client, ie. will be sent to a + // webservice that performs the id token verification and token + // exchange + // 2. The code is for this client and, for security reasons, the + // application developer must verify the id_token signature and + // c_hash before calling the token endpoint + OIDAuthState *authState = [[OIDAuthState alloc] + initWithAuthorizationResponse:authorizationResponse]; + callback(authState, authorizationError); + } + } else { + callback(nil, authorizationError); + } + }]; + return authFlowSession; +} + +#pragma mark - Initializers + +- (nonnull instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithAuthorizationResponse:tokenResponse:)) + +/*! @brief Creates an auth state from an authorization response. + @param authorizationResponse The authorization response. + */ +- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse { + return [self initWithAuthorizationResponse:authorizationResponse tokenResponse:nil]; +} + + +/*! @brief Designated initializer. + @param authorizationResponse The authorization response. + @discussion Creates an auth state from an authorization response and token response. + */ +- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse + tokenResponse:(nullable OIDTokenResponse *)tokenResponse { + return [self initWithAuthorizationResponse:authorizationResponse + tokenResponse:tokenResponse + registrationResponse:nil]; +} + +/*! @brief Creates an auth state from an registration response. + @param registrationResponse The registration response. + */ +- (instancetype)initWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse { + return [self initWithAuthorizationResponse:nil + tokenResponse:nil + registrationResponse:registrationResponse]; +} + +- (instancetype)initWithAuthorizationResponse: + (nullable OIDAuthorizationResponse *)authorizationResponse + tokenResponse:(nullable OIDTokenResponse *)tokenResponse + registrationResponse:(nullable OIDRegistrationResponse *)registrationResponse { + self = [super init]; + if (self) { + _pendingActionsSyncObject = [[NSObject alloc] init]; + + if (registrationResponse) { + [self updateWithRegistrationResponse:registrationResponse]; + } + + if (authorizationResponse) { + [self updateWithAuthorizationResponse:authorizationResponse error:nil]; + } + + if (tokenResponse) { + [self updateWithTokenResponse:tokenResponse error:nil]; + } + } + return self; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, isAuthorized: %@, refreshToken: \"%@\", " + "scope: \"%@\", accessToken: \"%@\", " + "accessTokenExpirationDate: %@, idToken: \"%@\", " + "lastAuthorizationResponse: %@, lastTokenResponse: %@, " + "lastRegistrationResponse: %@, authorizationError: %@>", + NSStringFromClass([self class]), + (void *)self, + (self.isAuthorized) ? @"YES" : @"NO", + [OIDTokenUtilities redact:_refreshToken], + _scope, + [OIDTokenUtilities redact:self.accessToken], + self.accessTokenExpirationDate, + [OIDTokenUtilities redact:self.idToken], + _lastAuthorizationResponse, + _lastTokenResponse, + _lastRegistrationResponse, + _authorizationError]; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + _lastAuthorizationResponse = [aDecoder decodeObjectOfClass:[OIDAuthorizationResponse class] + forKey:kLastAuthorizationResponseKey]; + _lastTokenResponse = [aDecoder decodeObjectOfClass:[OIDTokenResponse class] + forKey:kLastTokenResponseKey]; + self = [self initWithAuthorizationResponse:_lastAuthorizationResponse + tokenResponse:_lastTokenResponse]; + if (self) { + _authorizationError = + [aDecoder decodeObjectOfClass:[NSError class] forKey:kAuthorizationErrorKey]; + _scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey]; + _refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey]; + _needsTokenRefresh = [aDecoder decodeBoolForKey:kNeedsTokenRefreshKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_lastAuthorizationResponse forKey:kLastAuthorizationResponseKey]; + [aCoder encodeObject:_lastTokenResponse forKey:kLastTokenResponseKey]; + if (_authorizationError) { + NSError *codingSafeAuthorizationError = [NSError errorWithDomain:_authorizationError.domain + code:_authorizationError.code + userInfo:nil]; + [aCoder encodeObject:codingSafeAuthorizationError forKey:kAuthorizationErrorKey]; + } + [aCoder encodeObject:_scope forKey:kScopeKey]; + [aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey]; + [aCoder encodeBool:_needsTokenRefresh forKey:kNeedsTokenRefreshKey]; +} + +#pragma mark - Private convenience getters + +- (NSString *)accessToken { + if (_authorizationError) { + return nil; + } + return _lastTokenResponse ? _lastTokenResponse.accessToken + : _lastAuthorizationResponse.accessToken; +} + +- (NSString *)tokenType { + if (_authorizationError) { + return nil; + } + return _lastTokenResponse ? _lastTokenResponse.tokenType + : _lastAuthorizationResponse.tokenType; +} + +- (NSDate *)accessTokenExpirationDate { + if (_authorizationError) { + return nil; + } + return _lastTokenResponse ? _lastTokenResponse.accessTokenExpirationDate + : _lastAuthorizationResponse.accessTokenExpirationDate; +} + +- (NSString *)idToken { + if (_authorizationError) { + return nil; + } + return _lastTokenResponse ? _lastTokenResponse.idToken + : _lastAuthorizationResponse.idToken; +} + +#pragma mark - Getters + +- (BOOL)isAuthorized { + return !self.authorizationError && (self.accessToken || self.idToken || self.refreshToken); +} + +#pragma mark - Updating the state + +- (void)updateWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse { + _lastRegistrationResponse = registrationResponse; + _refreshToken = nil; + _scope = nil; + _lastAuthorizationResponse = nil; + _lastTokenResponse = nil; + _authorizationError = nil; + [self didChangeState]; +} + +- (void)updateWithAuthorizationResponse:(nullable OIDAuthorizationResponse *)authorizationResponse + error:(nullable NSError *)error { + // If the error is an OAuth authorization error, updates the state. Other errors are ignored. + if (error.domain == OIDOAuthAuthorizationErrorDomain) { + [self updateWithAuthorizationError:error]; + return; + } + if (!authorizationResponse) { + return; + } + + _lastAuthorizationResponse = authorizationResponse; + + // clears the last token response and refresh token as these now relate to an old authorization + // that is no longer relevant + _lastTokenResponse = nil; + _refreshToken = nil; + _authorizationError = nil; + + // if the response's scope is nil, it means that it equals that of the request + // see: https://tools.ietf.org/html/rfc6749#section-5.1 + _scope = (authorizationResponse.scope) ? authorizationResponse.scope + : authorizationResponse.request.scope; + + [self didChangeState]; +} + +- (void)updateWithTokenResponse:(nullable OIDTokenResponse *)tokenResponse + error:(nullable NSError *)error { + if (_authorizationError) { + // Calling updateWithTokenResponse while in an error state probably means the developer obtained + // a new token and did the exchange without also calling updateWithAuthorizationResponse. + // Attempts to handle gracefully, but warns the developer that this is unexpected. + NSLog(@"OIDAuthState:updateWithTokenResponse should not be called in an error state [%@] call" + "updateWithAuthorizationResponse with the result of the fresh authorization response" + "first", + _authorizationError); + + _authorizationError = nil; + } + + // If the error is an OAuth authorization error, updates the state. Other errors are ignored. + if (error.domain == OIDOAuthTokenErrorDomain) { + [self updateWithAuthorizationError:error]; + return; + } + if (!tokenResponse) { + return; + } + + _lastTokenResponse = tokenResponse; + + // updates the scope and refresh token if they are present on the TokenResponse. + // according to the spec, these may be changed by the server, including when refreshing the + // access token. See: https://tools.ietf.org/html/rfc6749#section-5.1 and + // https://tools.ietf.org/html/rfc6749#section-6 + if (tokenResponse.scope) { + _scope = tokenResponse.scope; + } + if (tokenResponse.refreshToken) { + _refreshToken = tokenResponse.refreshToken; + } + + [self didChangeState]; +} + +- (void)updateWithAuthorizationError:(NSError *)oauthError { + _authorizationError = oauthError; + + [self didChangeState]; + + [_errorDelegate authState:self didEncounterAuthorizationError:oauthError]; +} + +#pragma mark - OAuth Requests + +- (OIDTokenRequest *)tokenRefreshRequest { + return [self tokenRefreshRequestWithAdditionalParameters:nil]; +} + +- (OIDTokenRequest *)tokenRefreshRequestWithAdditionalParameters: + (NSDictionary *)additionalParameters { + + // TODO: Add unit test to confirm exception is thrown when expected + + if (!_refreshToken) { + [OIDErrorUtilities raiseException:kRefreshTokenRequestException]; + } + return [[OIDTokenRequest alloc] + initWithConfiguration:_lastAuthorizationResponse.request.configuration + grantType:OIDGrantTypeRefreshToken + authorizationCode:nil + redirectURL:nil + clientID:_lastAuthorizationResponse.request.clientID + clientSecret:_lastAuthorizationResponse.request.clientSecret + scope:nil + refreshToken:_refreshToken + codeVerifier:nil + additionalParameters:additionalParameters]; +} + +#pragma mark - Stateful Actions + +- (void)didChangeState { + [_stateChangeDelegate didChangeState:self]; +} + +- (void)setNeedsTokenRefresh { + _needsTokenRefresh = YES; +} + +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action { + [self performActionWithFreshTokens:action additionalRefreshParameters:nil]; +} + +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters: + (nullable NSDictionary *)additionalParameters { + [self performActionWithFreshTokens:action + additionalRefreshParameters:additionalParameters + dispatchQueue:dispatch_get_main_queue()]; +} + +- (void)performActionWithFreshTokens:(OIDAuthStateAction)action + additionalRefreshParameters: + (nullable NSDictionary *)additionalParameters + dispatchQueue:(dispatch_queue_t)dispatchQueue { + + if ([self isTokenFresh]) { + // access token is valid within tolerance levels, perform action + dispatch_async(dispatchQueue, ^{ + action(self.accessToken, self.idToken, nil); + }); + return; + } + + if (!_refreshToken) { + // no refresh token available and token has expired + NSError *tokenRefreshError = [ + OIDErrorUtilities errorWithCode:OIDErrorCodeTokenRefreshError + underlyingError:nil + description:@"Unable to refresh expired token without a refresh token."]; + dispatch_async(dispatchQueue, ^{ + action(nil, nil, tokenRefreshError); + }); + return; + } + + // access token is expired, first refresh the token, then perform action + NSAssert(_pendingActionsSyncObject, @"_pendingActionsSyncObject cannot be nil", @""); + OIDAuthStatePendingAction* pendingAction = + [[OIDAuthStatePendingAction alloc] initWithAction:action andDispatchQueue:dispatchQueue]; + @synchronized(_pendingActionsSyncObject) { + // if a token is already in the process of being refreshed, adds to pending actions + if (_pendingActions) { + [_pendingActions addObject:pendingAction]; + return; + } + + // creates a list of pending actions, starting with this one + _pendingActions = [NSMutableArray arrayWithObject:pendingAction]; + } + + // refresh the tokens + OIDTokenRequest *tokenRefreshRequest = + [self tokenRefreshRequestWithAdditionalParameters:additionalParameters]; + [OIDAuthorizationService performTokenRequest:tokenRefreshRequest + originalAuthorizationResponse:_lastAuthorizationResponse + callback:^(OIDTokenResponse *_Nullable response, + NSError *_Nullable error) { + // update OIDAuthState based on response + if (response) { + self->_needsTokenRefresh = NO; + [self updateWithTokenResponse:response error:nil]; + } else { + if (error.domain == OIDOAuthTokenErrorDomain) { + self->_needsTokenRefresh = NO; + [self updateWithAuthorizationError:error]; + } else { + if ([self->_errorDelegate respondsToSelector: + @selector(authState:didEncounterTransientError:)]) { + [self->_errorDelegate authState:self didEncounterTransientError:error]; + } + } + } + + // nil the pending queue and process everything that was queued up + NSArray *actionsToProcess; + @synchronized(self->_pendingActionsSyncObject) { + actionsToProcess = self->_pendingActions; + self->_pendingActions = nil; + } + for (OIDAuthStatePendingAction* actionToProcess in actionsToProcess) { + dispatch_async(actionToProcess.dispatchQueue, ^{ + actionToProcess.action(self.accessToken, self.idToken, error); + }); + } + }]; +} + +#pragma mark - + +/*! @fn isTokenFresh + @brief Determines whether a token refresh request must be made to refresh the tokens. + */ +- (BOOL)isTokenFresh { + if (_needsTokenRefresh) { + // forced refresh + return NO; + } + + if (!self.accessTokenExpirationDate) { + // if there is no expiration time but we have an access token, it is assumed to never expire + return !!self.accessToken; + } + + // has the token expired? + BOOL tokenFresh = [self.accessTokenExpirationDate timeIntervalSinceNow] > kExpiryTimeTolerance; + return tokenFresh; +} + +@end + + diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateChangeDelegate.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateChangeDelegate.h new file mode 100644 index 00000000..2570df13 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateChangeDelegate.h @@ -0,0 +1,39 @@ +/*! @file OIDAuthStateChangeDelegate.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthState; + +NS_ASSUME_NONNULL_BEGIN + +/*! @protocol OIDAuthStateChangeDelegate + @brief Delegate of the OIDAuthState used to monitor various changes in state. + */ +@protocol OIDAuthStateChangeDelegate + +/*! @brief Called when the authorization state changes and any backing storage needs to be updated. + @param state The @c OIDAuthState that changed. + @discussion If you are storing the authorization state, you should update the storage when the + state changes. + */ +- (void)didChangeState:(OIDAuthState *)state; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateErrorDelegate.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateErrorDelegate.h new file mode 100644 index 00000000..91a9b1cd --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthStateErrorDelegate.h @@ -0,0 +1,62 @@ +/*! @file OIDAuthStateErrorDelegate.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthState; + +NS_ASSUME_NONNULL_BEGIN + +/*! @protocol OIDAuthStateErrorDelegate + @brief Delegate of the OIDAuthState used to monitor errors. + */ +@protocol OIDAuthStateErrorDelegate + +/*! @brief Called when an authentication occurs, which indicates the auth session is invalid. + @param state The @c OIDAuthState on which the error occurred. + @param error The authorization error. + @discussion This is a hard error (not a transient network issue) that indicates a problem with + the authorization. You should stop using the @c OIDAuthState when such an error is + encountered. If the \NSError_code is @c ::OIDErrorCodeOAuthInvalidGrant then + the session may be recoverable with user interaction (i.e. re-authentication). In all cases + you should consider the user unauthorized, and remove locally cached resources that require + that authorization. @c OIDAuthState will call this method automatically if it encounters + an OAuth error (that is, an HTTP 400 response with a valid OAuth error response) during + authorization or token refresh (such as performed automatically when using + @c OIDAuthState.performActionWithFreshTokens:). You can signal authorization errors with + @c OIDAuthState.updateWithAuthorizationError:. + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +- (void)authState:(OIDAuthState *)state didEncounterAuthorizationError:(NSError *)error; + +@optional + +/*! @brief Called when a network or other transient error occurs. + @param state The @c OIDAuthState on which the error occurred. + @param error The transient error. + @discussion This is a soft error, typically network related. The @c OIDAuthState is likely + still valid, and should not be discarded. Retry the request using an incremental backoff + strategy. This is only called when using the @c OIDAuthState convenience methods such as + @c OIDAuthState.performActionWithFreshTokens:. If you are refreshing the tokens yourself + outside of @c OIDAuthState class, it will never be called. + */ +- (void)authState:(OIDAuthState *)state didEncounterTransientError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.h new file mode 100644 index 00000000..594f01d8 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.h @@ -0,0 +1,250 @@ +/*! @file OIDAuthorizationRequest.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +// These files only declare string constants useful for constructing a @c OIDAuthorizationRequest, +// so they are imported here for convenience. +#import "OIDExternalUserAgentRequest.h" +#import "OIDResponseTypes.h" +#import "OIDScopes.h" + +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief The @c code_challenge_method value for the S256 code challenge. + @see https://tools.ietf.org/html/rfc7636#section-4.3 + */ +extern NSString *const OIDOAuthorizationRequestCodeChallengeMethodS256; + + +/*! @brief Represents an authorization request. + @see https://tools.ietf.org/html/rfc6749#section-4 + @see https://tools.ietf.org/html/rfc6749#section-4.1.1 + */ +@interface OIDAuthorizationRequest : + NSObject + +/*! @brief The service's configuration. + @remarks This configuration specifies how to connect to a particular OAuth provider. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @brief The expected response type. + @remarks response_type + @discussion Generally 'code' if pure OAuth, otherwise a space-delimited list of of response + types including 'code', 'token', and 'id_token' for OpenID Connect. + @see https://tools.ietf.org/html/rfc6749#section-3.1.1 + @see http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3 + */ +@property(nonatomic, readonly) NSString *responseType; + +/*! @brief The client identifier. + @remarks client_id + @see https://tools.ietf.org/html/rfc6749#section-2.2 + */ +@property(nonatomic, readonly) NSString *clientID; + +/*! @brief The client secret. + @remarks client_secret + @discussion The client secret is used to prove that identity of the client when exchaning an + authorization code for an access token. + The client secret is not passed in the authorizationRequestURL. It is only used when + exchanging the authorization code for an access token. + @see https://tools.ietf.org/html/rfc6749#section-2.3.1 + */ +@property(nonatomic, readonly, nullable) NSString *clientSecret; + +/*! @brief The value of the scope parameter is expressed as a list of space-delimited, + case-sensitive strings. + @remarks scope + @see https://tools.ietf.org/html/rfc6749#section-3.3 + */ +@property(nonatomic, readonly, nullable) NSString *scope; + +/*! @brief The client's redirect URI. + @remarks redirect_uri + @see https://tools.ietf.org/html/rfc6749#section-3.1.2 + */ +@property(nonatomic, readonly, nullable) NSURL *redirectURL; + +/*! @brief An opaque value used by the client to maintain state between the request and callback. + @remarks state + @discussion If this value is not explicitly set, this library will automatically add state and + perform appropriate validation of the state in the authorization response. It is recommended + that the default implementation of this parameter be used wherever possible. Typically used + to prevent CSRF attacks, as recommended in RFC6819 Section 5.3.5. + @see https://tools.ietf.org/html/rfc6749#section-4.1.1 + @see https://tools.ietf.org/html/rfc6819#section-5.3.5 + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @brief String value used to associate a Client session with an ID Token, and to mitigate replay + attacks. The value is passed through unmodified from the Authentication Request to the ID + Token. Sufficient entropy MUST be present in the nonce values used to prevent attackers from + guessing values. + @remarks nonce + @discussion If this value is not explicitly set, this library will automatically add nonce and + perform appropriate validation of the nonce in the ID Token. + @see https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + */ +@property(nonatomic, readonly, nullable) NSString *nonce; + +/*! @brief The PKCE code verifier. + @remarks code_verifier + @discussion The code verifier itself is not included in the authorization request that is sent + on the wire, but needs to be in the token exchange request. + @c OIDAuthorizationResponse.tokenExchangeRequest will create a @c OIDTokenRequest that + includes this parameter automatically. + @see https://tools.ietf.org/html/rfc7636#section-4.1 + */ +@property(nonatomic, readonly, nullable) NSString *codeVerifier; + +/*! @brief The PKCE code challenge, derived from #codeVerifier. + @remarks code_challenge + @see https://tools.ietf.org/html/rfc7636#section-4.2 + */ +@property(nonatomic, readonly, nullable) NSString *codeChallenge; + +/*! @brief The method used to compute the @c #codeChallenge + @remarks code_challenge_method + @see https://tools.ietf.org/html/rfc7636#section-4.3 + */ +@property(nonatomic, readonly, nullable) NSString *codeChallengeMethod; + +/*! @brief The client's additional authorization parameters. + @see https://tools.ietf.org/html/rfc6749#section-3.1 + */ +@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters; + +/*! @internal + @brief Unavailable. Please use + @c initWithConfiguration:clientId:scopes:redirectURL:responseType:additionalParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Creates an authorization request with opinionated defaults (a secure @c state, and + PKCE with S256 as the @c code_challenge_method). + @param configuration The service's configuration. + @param clientID The client identifier. + @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec. + @param redirectURL The client's redirect URI. + @param responseType The expected response type. + @param additionalParameters The client's additional authorization parameters. + @remarks This convenience initializer generates a state parameter and PKCE challenges + automatically. + */ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + scopes:(nullable NSArray *)scopes + redirectURL:(NSURL *)redirectURL + responseType:(NSString *)responseType + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Creates an authorization request with opinionated defaults (a secure @c state, @c nonce, + and PKCE with S256 as the @c code_challenge_method). + @param configuration The service's configuration. + @param clientID The client identifier. + @param clientSecret The client secret. + @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec. + @param redirectURL The client's redirect URI. + @param responseType The expected response type. + @param additionalParameters The client's additional authorization parameters. + @remarks This convenience initializer generates a state parameter and PKCE challenges + automatically. + */ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scopes:(nullable NSArray *)scopes + redirectURL:(NSURL *)redirectURL + responseType:(NSString *)responseType + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Designated initializer. + @param configuration The service's configuration. + @param clientID The client identifier. + @param scope A scope string per the OAuth2 spec (a space-delimited set of scopes). + @param redirectURL The client's redirect URI. + @param responseType The expected response type. + @param state An opaque value used by the client to maintain state between the request and + callback. + @param nonce String value used to associate a Client session with an ID Token. Can be set to nil + if not using OpenID Connect, although pure OAuth servers should ignore params they don't + understand anyway. + @param codeVerifier The PKCE code verifier. See @c OIDAuthorizationRequest.generateCodeVerifier. + @param codeChallenge The PKCE code challenge, calculated from the code verifier such as with + @c OIDAuthorizationRequest.codeChallengeS256ForVerifier:. + @param codeChallengeMethod The PKCE code challenge method. + ::OIDOAuthorizationRequestCodeChallengeMethodS256 when + @c OIDAuthorizationRequest.codeChallengeS256ForVerifier: is used to create the code + challenge. + @param additionalParameters The client's additional authorization parameters. + */ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scope:(nullable NSString *)scope + redirectURL:(nullable NSURL *)redirectURL + responseType:(NSString *)responseType + state:(nullable NSString *)state + nonce:(nullable NSString *)nonce + codeVerifier:(nullable NSString *)codeVerifier + codeChallenge:(nullable NSString *)codeChallenge + codeChallengeMethod:(nullable NSString *)codeChallengeMethod + additionalParameters:(nullable NSDictionary *)additionalParameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Constructs the request URI by adding the request parameters to the query component of the + authorization endpoint URI using the "application/x-www-form-urlencoded" format. + @return A URL representing the authorization request. + @see https://tools.ietf.org/html/rfc6749#section-4.1.1 + */ +- (NSURL *)authorizationRequestURL; + +/*! @brief Generates an OAuth state param using a random source. + @return The generated state. + @see https://tools.ietf.org/html/rfc6819#section-5.3.5 + */ ++ (nullable NSString *)generateState; + +/*! @brief Constructs a PKCE-compliant code verifier. + @return The generated code verifier. + @see https://tools.ietf.org/html/rfc7636#section-4.1 + */ ++ (nullable NSString *)generateCodeVerifier; + +/*! @brief Creates a PKCE S256 codeChallenge from the codeVerifier. + @param codeVerifier The code verifier from which the code challenge will be derived. + @return The generated code challenge. + @details Generate a secure code verifier to pass into this method with + @c OIDAuthorizationRequest.generateCodeVerifier. The matching @c #codeChallengeMethod for + @c #codeChallenge%s created by this method is + ::OIDOAuthorizationRequestCodeChallengeMethodS256. + @see https://tools.ietf.org/html/rfc7636#section-4.1 + */ ++ (nullable NSString *)codeChallengeS256ForVerifier:(nullable NSString *)codeVerifier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.m new file mode 100644 index 00000000..ccfacda0 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationRequest.m @@ -0,0 +1,351 @@ +/*! @file OIDAuthorizationRequest.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthorizationRequest.h" + +#import "OIDDefines.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDTokenUtilities.h" +#import "OIDURLQueryComponent.h" + +/*! @brief The key for the @c configuration property for @c NSSecureCoding + */ +static NSString *const kConfigurationKey = @"configuration"; + +/*! @brief Key used to encode the @c responseType property for @c NSSecureCoding, and on the URL + request. + */ +static NSString *const kResponseTypeKey = @"response_type"; + +/*! @brief Key used to encode the @c clientID property for @c NSSecureCoding, and on the URL + request. + */ +static NSString *const kClientIDKey = @"client_id"; + +/*! @brief Key used to encode the @c clientSecret property for @c NSSecureCoding. + */ +static NSString *const kClientSecretKey = @"client_secret"; + +/*! @brief Key used to encode the @c scope property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kScopeKey = @"scope"; + +/*! @brief Key used to encode the @c redirectURL property for @c NSSecureCoding, and on the URL + request. + */ +static NSString *const kRedirectURLKey = @"redirect_uri"; + +/*! @brief Key used to encode the @c state property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief Key used to encode the @c nonce property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kNonceKey = @"nonce"; + +/*! @brief Key used to encode the @c codeVerifier property for @c NSSecureCoding. + */ +static NSString *const kCodeVerifierKey = @"code_verifier"; + +/*! @brief Key used to send the @c codeChallenge on the URL request. + */ +static NSString *const kCodeChallengeKey = @"code_challenge"; + +/*! @brief Key used to send the @c codeChallengeMethod on the URL request. + */ +static NSString *const kCodeChallengeMethodKey = @"code_challenge_method"; + +/*! @brief Key used to encode the @c additionalParameters property for + @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +/*! @brief Number of random bytes generated for the @ state. + */ +static NSUInteger const kStateSizeBytes = 32; + +/*! @brief Number of random bytes generated for the @ codeVerifier. + */ +static NSUInteger const kCodeVerifierBytes = 32; + +/*! @brief Assertion text for unsupported response types. + */ +static NSString *const OIDOAuthUnsupportedResponseTypeMessage = + @"The response_type \"%@\" isn't supported. AppAuth only supports the \"code\" or \"code id_token\" response_type."; + +/*! @brief Code challenge request method. + */ +NSString *const OIDOAuthorizationRequestCodeChallengeMethodS256 = @"S256"; + +@implementation OIDAuthorizationRequest + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER( + @selector(initWithConfiguration: + clientId: + scopes: + redirectURL: + responseType: + additionalParameters:) + ) + +/*! @brief Check if the response type is one AppAuth supports + @remarks AppAuth only supports the `code` and `code id_token` response types. + @see https://github.com/openid/AppAuth-iOS/issues/98 + @see https://github.com/openid/AppAuth-iOS/issues/292 + */ ++ (BOOL)isSupportedResponseType:(NSString *)responseType +{ + NSString *codeIdToken = [@[OIDResponseTypeCode, OIDResponseTypeIDToken] + componentsJoinedByString:@" "]; + NSString *idTokenCode = [@[OIDResponseTypeIDToken, OIDResponseTypeCode] + componentsJoinedByString:@" "]; + + return [responseType isEqualToString:OIDResponseTypeCode] + || [responseType isEqualToString:codeIdToken] + || [responseType isEqualToString:idTokenCode]; +} + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scope:(nullable NSString *)scope + redirectURL:(NSURL *)redirectURL + responseType:(NSString *)responseType + state:(nullable NSString *)state + nonce:(nullable NSString *)nonce + codeVerifier:(nullable NSString *)codeVerifier + codeChallenge:(nullable NSString *)codeChallenge + codeChallengeMethod:(nullable NSString *)codeChallengeMethod + additionalParameters:(nullable NSDictionary *)additionalParameters +{ + self = [super init]; + if (self) { + _configuration = [configuration copy]; + _clientID = [clientID copy]; + _clientSecret = [clientSecret copy]; + _scope = [scope copy]; + _redirectURL = [redirectURL copy]; + _responseType = [responseType copy]; + if (![[self class] isSupportedResponseType:_responseType]) { + NSAssert(NO, OIDOAuthUnsupportedResponseTypeMessage, _responseType); + return nil; + } + _state = [state copy]; + _nonce = [nonce copy]; + _codeVerifier = [codeVerifier copy]; + _codeChallenge = [codeChallenge copy]; + _codeChallengeMethod = [codeChallengeMethod copy]; + + _additionalParameters = + [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES]; + } + return self; +} + +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + clientSecret:(NSString *)clientSecret + scopes:(nullable NSArray *)scopes + redirectURL:(NSURL *)redirectURL + responseType:(NSString *)responseType + additionalParameters:(nullable NSDictionary *)additionalParameters { + + // generates PKCE code verifier and challenge + NSString *codeVerifier = [[self class] generateCodeVerifier]; + NSString *codeChallenge = [[self class] codeChallengeS256ForVerifier:codeVerifier]; + + return [self initWithConfiguration:configuration + clientId:clientID + clientSecret:clientSecret + scope:[OIDScopeUtilities scopesWithArray:scopes] + redirectURL:redirectURL + responseType:responseType + state:[[self class] generateState] + nonce:[[self class] generateState] + codeVerifier:codeVerifier + codeChallenge:codeChallenge + codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256 + additionalParameters:additionalParameters]; +} + +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + clientId:(NSString *)clientID + scopes:(nullable NSArray *)scopes + redirectURL:(NSURL *)redirectURL + responseType:(NSString *)responseType + additionalParameters:(nullable NSDictionary *)additionalParameters { + return [self initWithConfiguration:configuration + clientId:clientID + clientSecret:nil + scopes:scopes + redirectURL:redirectURL + responseType:responseType + additionalParameters:additionalParameters]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDServiceConfiguration *configuration = + [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] + forKey:kConfigurationKey]; + NSString *responseType = [aDecoder decodeObjectOfClass:[NSString class] forKey:kResponseTypeKey]; + NSString *clientID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientIDKey]; + NSString *clientSecret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientSecretKey]; + NSString *scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey]; + NSURL *redirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kRedirectURLKey]; + NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey]; + NSString *nonce = [aDecoder decodeObjectOfClass:[NSString class] forKey:kNonceKey]; + NSString *codeVerifier = [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeVerifierKey]; + NSString *codeChallenge = + [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeChallengeKey]; + NSString *codeChallengeMethod = + [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeChallengeMethodKey]; + NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ + [NSDictionary class], + [NSString class] + ]]; + NSDictionary *additionalParameters = + [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses + forKey:kAdditionalParametersKey]; + + self = [self initWithConfiguration:configuration + clientId:clientID + clientSecret:clientSecret + scope:scope + redirectURL:redirectURL + responseType:responseType + state:state + nonce:nonce + codeVerifier:codeVerifier + codeChallenge:codeChallenge + codeChallengeMethod:codeChallengeMethod + additionalParameters:additionalParameters]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_configuration forKey:kConfigurationKey]; + [aCoder encodeObject:_responseType forKey:kResponseTypeKey]; + [aCoder encodeObject:_clientID forKey:kClientIDKey]; + [aCoder encodeObject:_clientSecret forKey:kClientSecretKey]; + [aCoder encodeObject:_scope forKey:kScopeKey]; + [aCoder encodeObject:_redirectURL forKey:kRedirectURLKey]; + [aCoder encodeObject:_state forKey:kStateKey]; + [aCoder encodeObject:_nonce forKey:kNonceKey]; + [aCoder encodeObject:_codeVerifier forKey:kCodeVerifierKey]; + [aCoder encodeObject:_codeChallenge forKey:kCodeChallengeKey]; + [aCoder encodeObject:_codeChallengeMethod forKey:kCodeChallengeMethodKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, request: %@>", + NSStringFromClass([self class]), + (void *)self, + self.authorizationRequestURL]; +} + +#pragma mark - State and PKCE verifier/challenge generation Methods + ++ (nullable NSString *)generateCodeVerifier { + return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes]; +} + ++ (nullable NSString *)generateState { + return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; +} + ++ (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier { + if (!codeVerifier) { + return nil; + } + // generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2 + // code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) + // NB. the ASCII conversion on the code_verifier entropy was done at time of generation. + NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier]; + return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier]; +} + +#pragma mark - + +- (NSURL *)authorizationRequestURL { + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init]; + + // Required parameters. + [query addParameter:kResponseTypeKey value:_responseType]; + [query addParameter:kClientIDKey value:_clientID]; + + // Add any additional parameters the client has specified. + [query addParameters:_additionalParameters]; + + // Add optional parameters, as applicable. + if (_redirectURL) { + [query addParameter:kRedirectURLKey value:_redirectURL.absoluteString]; + } + if (_scope) { + [query addParameter:kScopeKey value:_scope]; + } + if (_state) { + [query addParameter:kStateKey value:_state]; + } + if (_nonce) { + [query addParameter:kNonceKey value:_nonce]; + } + if (_codeChallenge) { + [query addParameter:kCodeChallengeKey value:_codeChallenge]; + } + if (_codeChallengeMethod) { + [query addParameter:kCodeChallengeMethodKey value:_codeChallengeMethod]; + } + + // Construct the URL: + return [query URLByReplacingQueryInURL:_configuration.authorizationEndpoint]; +} + +#pragma mark - OIDExternalUserAgentRequest + +- (NSURL *)externalUserAgentRequestURL { + return [self authorizationRequestURL]; +} + +- (NSString *)redirectScheme { + return [[self redirectURL] scheme]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.h new file mode 100644 index 00000000..e7552fe5 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.h @@ -0,0 +1,128 @@ +/*! @file OIDAuthorizationResponse.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthorizationRequest; +@class OIDTokenRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents the response to an authorization request. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2 + @see https://tools.ietf.org/html/rfc6749#section-5.1 + @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse + */ +@interface OIDAuthorizationResponse : NSObject + +/*! @brief The request which was serviced. + */ +@property(nonatomic, readonly) OIDAuthorizationRequest *request; + +/*! @brief The authorization code generated by the authorization server. + @discussion Set when the response_type requested includes 'code'. + @remarks code + */ +@property(nonatomic, readonly, nullable) NSString *authorizationCode; + +/*! @brief REQUIRED if the "state" parameter was present in the client authorization request. The + exact value received from the client. + @remarks state + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @brief The access token generated by the authorization server. + @discussion Set when the response_type requested includes 'token'. + @remarks access_token + @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse + */ +@property(nonatomic, readonly, nullable) NSString *accessToken; + +/*! @brief The approximate expiration date & time of the access token. + @discussion Set when the response_type requested includes 'token'. + @remarks expires_in + @seealso OIDAuthorizationResponse.accessToken + @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse + */ +@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate; + +/*! @brief Typically "Bearer" when present. Otherwise, another token_type value that the Client has + negotiated with the Authorization Server. + @discussion Set when the response_type requested includes 'token'. + @remarks token_type + @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse + */ +@property(nonatomic, readonly, nullable) NSString *tokenType; + +/*! @brief ID Token value associated with the authenticated session. + @discussion Set when the response_type requested includes 'id_token'. + @remarks id_token + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + @see http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse + */ +@property(nonatomic, readonly, nullable) NSString *idToken; + +/*! @brief The scope of the access token. OPTIONAL, if identical to the scopes requested, otherwise, + REQUIRED. + @remarks scope + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *scope; + +/*! @brief Additional parameters returned from the authorization server. + */ +@property(nonatomic, readonly, nullable) + NSDictionary *> *additionalParameters; + +/*! @internal + @brief Unavailable. Please use initWithRequest:parameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Designated initializer. + @param request The serviced request. + @param parameters The decoded parameters returned from the Authorization Server. + @remarks Known parameters are extracted from the @c parameters parameter and the normative + properties are populated. Non-normative parameters are placed in the + @c #additionalParameters dictionary. + */ +- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request + parameters:(NSDictionary *> *)parameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Creates a token request suitable for exchanging an authorization code for an access + token. + @return A @c OIDTokenRequest suitable for exchanging an authorization code for an access + token. + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +- (nullable OIDTokenRequest *)tokenExchangeRequest; + +/*! @brief Creates a token request suitable for exchanging an authorization code for an access + token. + @param additionalParameters Additional parameters for the token request. + @return A @c OIDTokenRequest suitable for exchanging an authorization code for an access + token. + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +- (nullable OIDTokenRequest *)tokenExchangeRequestWithAdditionalParameters: + (nullable NSDictionary *)additionalParameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.m new file mode 100644 index 00000000..a8f92c75 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationResponse.m @@ -0,0 +1,210 @@ +/*! @file OIDAuthorizationResponse.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthorizationResponse.h" + +#import "OIDAuthorizationRequest.h" +#import "OIDDefines.h" +#import "OIDError.h" +#import "OIDFieldMapping.h" +#import "OIDTokenRequest.h" +#import "OIDTokenUtilities.h" + +/*! @brief The key for the @c authorizationCode property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kAuthorizationCodeKey = @"code"; + +/*! @brief The key for the @c state property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief The key for the @c accessToken property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kAccessTokenKey = @"access_token"; + +/*! @brief The key for the @c accessTokenExpirationDate property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kExpiresInKey = @"expires_in"; + +/*! @brief The key for the @c tokenType property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kTokenTypeKey = @"token_type"; + +/*! @brief The key for the @c idToken property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kIDTokenKey = @"id_token"; + +/*! @brief The key for the @c scope property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kScopeKey = @"scope"; + +/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +/*! @brief Key used to encode the @c request property for @c NSSecureCoding + */ +static NSString *const kRequestKey = @"request"; + +/*! @brief The exception thrown when a developer tries to create a token exchange request from an + authorization request with no authorization code. + */ +static NSString *const kTokenExchangeRequestException = + @"Attempted to create a token exchange request from an authorization response with no " + "authorization code."; + +@implementation OIDAuthorizationResponse + +/*! @brief Returns a mapping of incoming parameters to instance variables. + @return A mapping of incoming parameters to instance variables. + */ ++ (NSDictionary *)fieldMap { + static NSMutableDictionary *fieldMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fieldMap = [NSMutableDictionary dictionary]; + fieldMap[kStateKey] = + [[OIDFieldMapping alloc] initWithName:@"_state" type:[NSString class]]; + fieldMap[kAuthorizationCodeKey] = + [[OIDFieldMapping alloc] initWithName:@"_authorizationCode" type:[NSString class]]; + fieldMap[kAccessTokenKey] = + [[OIDFieldMapping alloc] initWithName:@"_accessToken" type:[NSString class]]; + fieldMap[kExpiresInKey] = + [[OIDFieldMapping alloc] initWithName:@"_accessTokenExpirationDate" + type:[NSDate class] + conversion:^id _Nullable(NSObject *_Nullable value) { + if (![value isKindOfClass:[NSNumber class]]) { + return value; + } + NSNumber *valueAsNumber = (NSNumber *)value; + return [NSDate dateWithTimeIntervalSinceNow:[valueAsNumber longLongValue]]; + }]; + fieldMap[kTokenTypeKey] = + [[OIDFieldMapping alloc] initWithName:@"_tokenType" type:[NSString class]]; + fieldMap[kIDTokenKey] = + [[OIDFieldMapping alloc] initWithName:@"_idToken" type:[NSString class]]; + fieldMap[kScopeKey] = + [[OIDFieldMapping alloc] initWithName:@"_scope" type:[NSString class]]; + }); + return fieldMap; +} + +#pragma mark - Initializers + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:)) + +- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request + parameters:(NSDictionary *> *)parameters { + self = [super init]; + if (self) { + _request = [request copy]; + NSDictionary *> *additionalParameters = + [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap] + parameters:parameters + instance:self]; + _additionalParameters = additionalParameters; + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDAuthorizationRequest *request = + [aDecoder decodeObjectOfClass:[OIDAuthorizationRequest class] forKey:kRequestKey]; + self = [self initWithRequest:request parameters:@{ }]; + if (self) { + [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self]; + _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes] + forKey:kAdditionalParametersKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_request forKey:kRequestKey]; + [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, authorizationCode: %@, state: \"%@\", accessToken: " + "\"%@\", accessTokenExpirationDate: %@, tokenType: %@, " + "idToken: \"%@\", scope: \"%@\", additionalParameters: %@, " + "request: %@>", + NSStringFromClass([self class]), + (void *)self, + _authorizationCode, + _state, + [OIDTokenUtilities redact:_accessToken], + _accessTokenExpirationDate, + _tokenType, + [OIDTokenUtilities redact:_idToken], + _scope, + _additionalParameters, + _request]; +} + +#pragma mark - + +- (OIDTokenRequest *)tokenExchangeRequest { + return [self tokenExchangeRequestWithAdditionalParameters:nil]; +} + +- (OIDTokenRequest *)tokenExchangeRequestWithAdditionalParameters: + (NSDictionary *)additionalParameters { + // TODO: add a unit test to confirm exception is thrown when expected and the request is created + // with the correct parameters. + if (!_authorizationCode) { + [NSException raise:kTokenExchangeRequestException + format:kTokenExchangeRequestException]; + } + return [[OIDTokenRequest alloc] initWithConfiguration:_request.configuration + grantType:OIDGrantTypeAuthorizationCode + authorizationCode:_authorizationCode + redirectURL:_request.redirectURL + clientID:_request.clientID + clientSecret:_request.clientSecret + scope:nil + refreshToken:nil + codeVerifier:_request.codeVerifier + additionalParameters:additionalParameters]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.h new file mode 100644 index 00000000..c8fee535 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.h @@ -0,0 +1,170 @@ +/*! @file OIDAuthorizationService.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthorization; +@class OIDAuthorizationRequest; +@class OIDAuthorizationResponse; +@class OIDEndSessionRequest; +@class OIDEndSessionResponse; +@class OIDRegistrationRequest; +@class OIDRegistrationResponse; +@class OIDServiceConfiguration; +@class OIDTokenRequest; +@class OIDTokenResponse; +@protocol OIDExternalUserAgent; +@protocol OIDExternalUserAgentSession; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents the type of block used as a callback for creating a service configuration from + a remote OpenID Connect Discovery document. + @param configuration The service configuration, if available. + @param error The error if an error occurred. + */ +typedef void (^OIDDiscoveryCallback)(OIDServiceConfiguration *_Nullable configuration, + NSError *_Nullable error); + +/*! @brief Represents the type of block used as a callback for various methods of + @c OIDAuthorizationService. + @param authorizationResponse The authorization response, if available. + @param error The error if an error occurred. + */ +typedef void (^OIDAuthorizationCallback)(OIDAuthorizationResponse *_Nullable authorizationResponse, + NSError *_Nullable error); + +/*! @brief Block used as a callback for the end-session request of @c OIDAuthorizationService. + @param endSessionResponse The end-session response, if available. + @param error The error if an error occurred. + */ +typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse, + NSError *_Nullable error); + +/*! @brief Represents the type of block used as a callback for various methods of + @c OIDAuthorizationService. + @param tokenResponse The token response, if available. + @param error The error if an error occurred. + */ +typedef void (^OIDTokenCallback)(OIDTokenResponse *_Nullable tokenResponse, + NSError *_Nullable error); + +/*! @brief Represents the type of dictionary used to specify additional querystring parameters + when making authorization or token endpoint requests. + */ +typedef NSDictionary *_Nullable OIDTokenEndpointParameters; + +/*! @brief Represents the type of block used as a callback for various methods of + @c OIDAuthorizationService. + @param registrationResponse The registration response, if available. + @param error The error if an error occurred. +*/ +typedef void (^OIDRegistrationCompletion)(OIDRegistrationResponse *_Nullable registrationResponse, + NSError *_Nullable error); + +/*! @brief Performs various OAuth and OpenID Connect related calls via the user agent or + \NSURLSession. + */ +@interface OIDAuthorizationService : NSObject + +/*! @brief The service's configuration. + @remarks Each authorization service is initialized with a configuration. This configuration + specifies how to connect to a particular OAuth provider. Clients should use separate + authorization service instances for each provider they wish to integrate with. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @internal + @brief Unavailable. This class should not be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Convenience method for creating an authorization service configuration from an OpenID + Connect compliant issuer URL. + @param issuerURL The service provider's OpenID Connect issuer. + @param completion A block which will be invoked when the authorization service configuration has + been created, or when an error has occurred. + @see https://openid.net/specs/openid-connect-discovery-1_0.html + */ ++ (void)discoverServiceConfigurationForIssuer:(NSURL *)issuerURL + completion:(OIDDiscoveryCallback)completion; + + +/*! @brief Convenience method for creating an authorization service configuration from an OpenID + Connect compliant identity provider's discovery document. + @param discoveryURL The URL of the service provider's OpenID Connect discovery document. + @param completion A block which will be invoked when the authorization service configuration has + been created, or when an error has occurred. + @see https://openid.net/specs/openid-connect-discovery-1_0.html + */ ++ (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL + completion:(OIDDiscoveryCallback)completion; + +/*! @brief Perform an authorization flow using a generic flow shim. + @param request The authorization request. + @param externalUserAgent Generic external user-agent that can present an authorization + request. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + */ ++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request + externalUserAgent:(id)externalUserAgent + callback:(OIDAuthorizationCallback)callback; + +/*! @brief Perform a logout request. + @param request The end-session logout request. + @param externalUserAgent Generic external user-agent that can present user-agent requests. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ ++ (id) + presentEndSessionRequest:(OIDEndSessionRequest *)request + externalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)callback; + +/*! @brief Performs a token request. + @param request The token request. + @param callback The method called when the request has completed or failed. + */ ++ (void)performTokenRequest:(OIDTokenRequest *)request callback:(OIDTokenCallback)callback; + +/*! @brief Performs a token request. + @param request The token request. + @param authorizationResponse The original authorization response related to this token request. + @param callback The method called when the request has completed or failed. + */ ++ (void)performTokenRequest:(OIDTokenRequest *)request + originalAuthorizationResponse:(OIDAuthorizationResponse *_Nullable)authorizationResponse + callback:(OIDTokenCallback)callback; + +/*! @brief Performs a registration request. + @param request The registration request. + @param completion The method called when the request has completed or failed. + */ ++ (void)performRegistrationRequest:(OIDRegistrationRequest *)request + completion:(OIDRegistrationCompletion)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.m new file mode 100644 index 00000000..cc749a3f --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDAuthorizationService.m @@ -0,0 +1,790 @@ +/*! @file OIDAuthorizationService.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDAuthorizationService.h" + +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDDefines.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDIDToken.h" +#import "OIDRegistrationRequest.h" +#import "OIDRegistrationResponse.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDURLQueryComponent.h" +#import "OIDURLSessionProvider.h" + +/*! @brief Path appended to an OpenID Connect issuer for discovery + @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig + */ +static NSString *const kOpenIDConfigurationWellKnownPath = @".well-known/openid-configuration"; + +/*! @brief Max allowable iat (Issued At) time skew + @see https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation + */ +static int const kOIDAuthorizationSessionIATMaxSkew = 600; + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDAuthorizationSession : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request + NS_DESIGNATED_INITIALIZER; + +@end + +@implementation OIDAuthorizationSession { + OIDAuthorizationRequest *_request; + id _externalUserAgent; + OIDAuthorizationCallback _pendingauthorizationFlowCallback; +} + +- (instancetype)initWithRequest:(OIDAuthorizationRequest *)request { + self = [super init]; + if (self) { + _request = [request copy]; + } + return self; +} + +- (void)presentAuthorizationWithExternalUserAgent:(id)externalUserAgent + callback:(OIDAuthorizationCallback)authorizationFlowCallback { + _externalUserAgent = externalUserAgent; + _pendingauthorizationFlowCallback = authorizationFlowCallback; + BOOL authorizationFlowStarted = + [_externalUserAgent presentExternalUserAgentRequest:_request session:self]; + if (!authorizationFlowStarted) { + NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError + underlyingError:nil + description:@"Unable to open Safari."]; + [self didFinishWithResponse:nil error:safariError]; + } +} + +- (void)cancel { + [self cancelWithCompletion:nil]; +} + +- (void)cancelWithCompletion:(nullable void (^)(void))completion { + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ + NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:nil + description:@"Authorization flow was cancelled."]; + [self didFinishWithResponse:nil error:error]; + if (completion) completion(); + }]; +} + +/*! @brief Does the redirection URL equal another URL down to the path component? + @param URL The first redirect URI to compare. + @param redirectionURL The second redirect URI to compare. + @return YES if the URLs match down to the path level (query params are ignored). + */ ++ (BOOL)URL:(NSURL *)URL matchesRedirectionURL:(NSURL *)redirectionURL { + NSURL *standardizedURL = [URL standardizedURL]; + NSURL *standardizedRedirectURL = [redirectionURL standardizedURL]; + + return [standardizedURL.scheme caseInsensitiveCompare:standardizedRedirectURL.scheme] == NSOrderedSame + && OIDIsEqualIncludingNil(standardizedURL.user, standardizedRedirectURL.user) + && OIDIsEqualIncludingNil(standardizedURL.password, standardizedRedirectURL.password) + && OIDIsEqualIncludingNil(standardizedURL.host, standardizedRedirectURL.host) + && OIDIsEqualIncludingNil(standardizedURL.port, standardizedRedirectURL.port) + && OIDIsEqualIncludingNil(standardizedURL.path, standardizedRedirectURL.path); +} + +- (BOOL)shouldHandleURL:(NSURL *)URL { + return [[self class] URL:URL matchesRedirectionURL:_request.redirectURL]; +} + +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL { + // rejects URLs that don't match redirect (these may be completely unrelated to the authorization) + if (![self shouldHandleURL:URL]) { + return NO; + } + + AppAuthRequestTrace(@"Authorization Response: %@", URL); + + // checks for an invalid state + if (!_pendingauthorizationFlowCallback) { + [NSException raise:OIDOAuthExceptionInvalidAuthorizationFlow + format:@"%@", OIDOAuthExceptionInvalidAuthorizationFlow, nil]; + } + + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] initWithURL:URL]; + + NSError *error; + OIDAuthorizationResponse *response = nil; + + // checks for an OAuth error response as per RFC6749 Section 4.1.2.1 + if (query.dictionaryValue[OIDOAuthErrorFieldError]) { + error = [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthAuthorizationErrorDomain + OAuthResponse:query.dictionaryValue + underlyingError:nil]; + } + + // no error, should be a valid OAuth 2.0 response + if (!error) { + response = [[OIDAuthorizationResponse alloc] initWithRequest:_request + parameters:query.dictionaryValue]; + + // verifies that the state in the response matches the state in the request, or both are nil + if (!OIDIsEqualIncludingNil(_request.state, response.state)) { + NSMutableDictionary *userInfo = [query.dictionaryValue mutableCopy]; + userInfo[NSLocalizedDescriptionKey] = + [NSString stringWithFormat:@"State mismatch, expecting %@ but got %@ in authorization " + "response %@", + _request.state, + response.state, + response]; + response = nil; + error = [NSError errorWithDomain:OIDOAuthAuthorizationErrorDomain + code:OIDErrorCodeOAuthAuthorizationClientError + userInfo:userInfo]; + } + } + + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ + [self didFinishWithResponse:response error:error]; + }]; + + return YES; +} + +- (void)failExternalUserAgentFlowWithError:(NSError *)error { + [self didFinishWithResponse:nil error:error]; +} + +/*! @brief Invokes the pending callback and performs cleanup. + @param response The authorization response, if any to return to the callback. + @param error The error, if any, to return to the callback. + */ +- (void)didFinishWithResponse:(nullable OIDAuthorizationResponse *)response + error:(nullable NSError *)error { + OIDAuthorizationCallback callback = _pendingauthorizationFlowCallback; + _pendingauthorizationFlowCallback = nil; + _externalUserAgent = nil; + if (callback) { + callback(response, error); + } +} + +@end + +@interface OIDEndSessionImplementation : NSObject { + // private variables + OIDEndSessionRequest *_request; + id _externalUserAgent; + OIDEndSessionCallback _pendingEndSessionCallback; +} +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request + NS_DESIGNATED_INITIALIZER; +@end + + +@implementation OIDEndSessionImplementation + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request { + self = [super init]; + if (self) { + _request = [request copy]; + } + return self; +} + +- (void)presentAuthorizationWithExternalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)authorizationFlowCallback { + _externalUserAgent = externalUserAgent; + _pendingEndSessionCallback = authorizationFlowCallback; + BOOL authorizationFlowStarted = + [_externalUserAgent presentExternalUserAgentRequest:_request session:self]; + if (!authorizationFlowStarted) { + NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError + underlyingError:nil + description:@"Unable to open Safari."]; + [self didFinishWithResponse:nil error:safariError]; + } +} + +- (void)cancel { + [self cancelWithCompletion:nil]; +} + +- (void)cancelWithCompletion:(nullable void (^)(void))completion { + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ + NSError *error = [OIDErrorUtilities + errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:nil + description:nil]; + [self didFinishWithResponse:nil error:error]; + if (completion) completion(); + }]; +} + +- (BOOL)shouldHandleURL:(NSURL *)URL { + // The logic of when to handle the URL is the same as for authorization requests: should match + // down to the path component. + return [[OIDAuthorizationSession class] URL:URL + matchesRedirectionURL:_request.postLogoutRedirectURL]; +} + +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL { + // rejects URLs that don't match redirect (these may be completely unrelated to the authorization) + if (![self shouldHandleURL:URL]) { + return NO; + } + // checks for an invalid state + if (!_pendingEndSessionCallback) { + [NSException raise:OIDOAuthExceptionInvalidAuthorizationFlow + format:@"%@", OIDOAuthExceptionInvalidAuthorizationFlow, nil]; + } + + + NSError *error; + OIDEndSessionResponse *response = nil; + + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] initWithURL:URL]; + response = [[OIDEndSessionResponse alloc] initWithRequest:_request + parameters:query.dictionaryValue]; + + // verifies that the state in the response matches the state in the request, or both are nil + if (!OIDIsEqualIncludingNil(_request.state, response.state)) { + NSMutableDictionary *userInfo = [query.dictionaryValue mutableCopy]; + userInfo[NSLocalizedDescriptionKey] = + [NSString stringWithFormat:@"State mismatch, expecting %@ but got %@ in authorization " + "response %@", + _request.state, + response.state, + response]; + response = nil; + error = [NSError errorWithDomain:OIDOAuthAuthorizationErrorDomain + code:OIDErrorCodeOAuthAuthorizationClientError + userInfo:userInfo]; + } + + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ + [self didFinishWithResponse:response error:error]; + }]; + + return YES; +} + +- (void)failExternalUserAgentFlowWithError:(NSError *)error { + [self didFinishWithResponse:nil error:error]; +} + +/*! @brief Invokes the pending callback and performs cleanup. + @param response The authorization response, if any to return to the callback. + @param error The error, if any, to return to the callback. + */ +- (void)didFinishWithResponse:(nullable OIDEndSessionResponse *)response + error:(nullable NSError *)error { + OIDEndSessionCallback callback = _pendingEndSessionCallback; + _pendingEndSessionCallback = nil; + _externalUserAgent = nil; + if (callback) { + callback(response, error); + } +} + +@end + +@implementation OIDAuthorizationService + ++ (void)discoverServiceConfigurationForIssuer:(NSURL *)issuerURL + completion:(OIDDiscoveryCallback)completion { + NSURL *fullDiscoveryURL = + [issuerURL URLByAppendingPathComponent:kOpenIDConfigurationWellKnownPath]; + + [[self class] discoverServiceConfigurationForDiscoveryURL:fullDiscoveryURL + completion:completion]; +} + ++ (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL + completion:(OIDDiscoveryCallback)completion { + + NSURLSession *session = [OIDURLSessionProvider session]; + NSURLSessionDataTask *task = + [session dataTaskWithURL:discoveryURL + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + // If we got any sort of error, just report it. + if (error || !data) { + NSString *errorDescription = + [NSString stringWithFormat:@"Connection error fetching discovery document '%@': %@.", + discoveryURL, + error.localizedDescription]; + error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError + underlyingError:error + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, error); + }); + return; + } + + NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response; + + // Check for non-200 status codes. + // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse + if (urlResponse.statusCode != 200) { + NSError *URLResponseError = [OIDErrorUtilities HTTPErrorWithHTTPResponse:urlResponse + data:data]; + NSString *errorDescription = + [NSString stringWithFormat:@"Non-200 HTTP response (%d) fetching discovery document " + "'%@'.", + (int)urlResponse.statusCode, + discoveryURL]; + error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError + underlyingError:URLResponseError + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, error); + }); + return; + } + + // Construct an OIDServiceDiscovery with the received JSON. + OIDServiceDiscovery *discovery = + [[OIDServiceDiscovery alloc] initWithJSONData:data error:&error]; + if (error || !discovery) { + NSString *errorDescription = + [NSString stringWithFormat:@"JSON error parsing document at '%@': %@", + discoveryURL, + error.localizedDescription]; + error = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError + underlyingError:error + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, error); + }); + return; + } + + // Create our service configuration with the discovery document and return it. + OIDServiceConfiguration *configuration = + [[OIDServiceConfiguration alloc] initWithDiscoveryDocument:discovery]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(configuration, nil); + }); + }]; + [task resume]; +} + +#pragma mark - Authorization Endpoint + ++ (id) presentAuthorizationRequest:(OIDAuthorizationRequest *)request + externalUserAgent:(id)externalUserAgent + callback:(OIDAuthorizationCallback)callback { + + AppAuthRequestTrace(@"Authorization Request: %@", request); + + OIDAuthorizationSession *flowSession = [[OIDAuthorizationSession alloc] initWithRequest:request]; + [flowSession presentAuthorizationWithExternalUserAgent:externalUserAgent callback:callback]; + return flowSession; +} + ++ (id) + presentEndSessionRequest:(OIDEndSessionRequest *)request + externalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)callback { + OIDEndSessionImplementation *flowSession = + [[OIDEndSessionImplementation alloc] initWithRequest:request]; + [flowSession presentAuthorizationWithExternalUserAgent:externalUserAgent callback:callback]; + return flowSession; +} + +#pragma mark - Token Endpoint + ++ (void)performTokenRequest:(OIDTokenRequest *)request callback:(OIDTokenCallback)callback { + [[self class] performTokenRequest:request + originalAuthorizationResponse:nil + callback:callback]; +} + ++ (void)performTokenRequest:(OIDTokenRequest *)request + originalAuthorizationResponse:(OIDAuthorizationResponse *_Nullable)authorizationResponse + callback:(OIDTokenCallback)callback { + + NSURLRequest *URLRequest = [request URLRequest]; + + AppAuthRequestTrace(@"Token Request: %@\nHeaders:%@\nHTTPBody: %@", + URLRequest.URL, + URLRequest.allHTTPHeaderFields, + [[NSString alloc] initWithData:URLRequest.HTTPBody + encoding:NSUTF8StringEncoding]); + + NSURLSession *session = [OIDURLSessionProvider session]; + [[session dataTaskWithRequest:URLRequest + completionHandler:^(NSData *_Nullable data, + NSURLResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + // A network error or server error occurred. + NSString *errorDescription = + [NSString stringWithFormat:@"Connection error making token request to '%@': %@.", + URLRequest.URL, + error.localizedDescription]; + NSError *returnedError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError + underlyingError:error + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, returnedError); + }); + return; + } + + NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *)response; + NSInteger statusCode = HTTPURLResponse.statusCode; + AppAuthRequestTrace(@"Token Response: HTTP Status %d\nHTTPBody: %@", + (int)statusCode, + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + if (statusCode != 200) { + // A server error occurred. + NSError *serverError = + [OIDErrorUtilities HTTPErrorWithHTTPResponse:HTTPURLResponse data:data]; + + // HTTP 4xx may indicate an RFC6749 Section 5.2 error response, attempts to parse as such. + if (statusCode >= 400 && statusCode < 500) { + NSError *jsonDeserializationError; + NSDictionary *> *json = + [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError]; + + // If the HTTP 4xx response parses as JSON and has an 'error' key, it's an OAuth error. + // These errors are special as they indicate a problem with the authorization grant. + if (json[OIDOAuthErrorFieldError]) { + NSError *oauthError = + [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthTokenErrorDomain + OAuthResponse:json + underlyingError:serverError]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, oauthError); + }); + return; + } + } + + // Status code indicates this is an error, but not an RFC6749 Section 5.2 error. + NSString *errorDescription = + [NSString stringWithFormat:@"Non-200 HTTP response (%d) making token request to '%@'.", + (int)statusCode, + URLRequest.URL]; + NSError *returnedError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeServerError + underlyingError:serverError + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, returnedError); + }); + return; + } + + NSError *jsonDeserializationError; + NSDictionary *> *json = + [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError]; + if (jsonDeserializationError) { + // A problem occurred deserializing the response/JSON. + NSString *errorDescription = + [NSString stringWithFormat:@"JSON error parsing token response: %@", + jsonDeserializationError.localizedDescription]; + NSError *returnedError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError + underlyingError:jsonDeserializationError + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, returnedError); + }); + return; + } + + OIDTokenResponse *tokenResponse = + [[OIDTokenResponse alloc] initWithRequest:request parameters:json]; + if (!tokenResponse) { + // A problem occurred constructing the token response from the JSON. + NSError *returnedError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeTokenResponseConstructionError + underlyingError:jsonDeserializationError + description:@"Token response invalid."]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, returnedError); + }); + return; + } + + // If an ID Token is included in the response, validates the ID Token following the rules + // in OpenID Connect Core Section 3.1.3.7 for features that AppAuth directly supports + // (which excludes rules #1, #4, #5, #7, #8, #12, and #13). Regarding rule #6, ID Tokens + // received by this class are received via direct communication between the Client and the Token + // Endpoint, thus we are exercising the option to rely only on the TLS validation. AppAuth + // has a zero dependencies policy, and verifying the JWT signature would add a dependency. + // Users of the library are welcome to perform the JWT signature verification themselves should + // they wish. + if (tokenResponse.idToken) { + OIDIDToken *idToken = [[OIDIDToken alloc] initWithIDTokenString:tokenResponse.idToken]; + if (!idToken) { + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenParsingError + underlyingError:nil + description:@"ID Token parsing failed"]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + + // OpenID Connect Core Section 3.1.3.7. rule #1 + // Not supported: AppAuth does not support JWT encryption. + + // OpenID Connect Core Section 3.1.3.7. rule #2 + // Validates that the issuer in the ID Token matches that of the discovery document. + NSURL *issuer = tokenResponse.request.configuration.issuer; + if (issuer && ![idToken.issuer isEqual:issuer]) { + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:@"Issuer mismatch"]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + + // OpenID Connect Core Section 3.1.3.7. rule #3 & Section 2 azp Claim + // Validates that the aud (audience) Claim contains the client ID, or that the azp + // (authorized party) Claim matches the client ID. + NSString *clientID = tokenResponse.request.clientID; + if (![idToken.audience containsObject:clientID] && + ![idToken.claims[@"azp"] isEqualToString:clientID]) { + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:@"Audience mismatch"]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + + // OpenID Connect Core Section 3.1.3.7. rules #4 & #5 + // Not supported. + + // OpenID Connect Core Section 3.1.3.7. rule #6 + // As noted above, AppAuth only supports the code flow which results in direct communication + // of the ID Token from the Token Endpoint to the Client, and we are exercising the option to + // use TSL server validation instead of checking the token signature. Users may additionally + // check the token signature should they wish. + + // OpenID Connect Core Section 3.1.3.7. rules #7 & #8 + // Not applicable. See rule #6. + + // OpenID Connect Core Section 3.1.3.7. rule #9 + // Validates that the current time is before the expiry time. + NSTimeInterval expiresAtDifference = [idToken.expiresAt timeIntervalSinceNow]; + if (expiresAtDifference < 0) { + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:@"ID Token expired"]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + + // OpenID Connect Core Section 3.1.3.7. rule #10 + // Validates that the issued at time is not more than +/- 10 minutes on the current time. + NSTimeInterval issuedAtDifference = [idToken.issuedAt timeIntervalSinceNow]; + if (fabs(issuedAtDifference) > kOIDAuthorizationSessionIATMaxSkew) { + NSString *message = + [NSString stringWithFormat:@"Issued at time is more than %d seconds before or after " + "the current time", + kOIDAuthorizationSessionIATMaxSkew]; + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:message]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + + // Only relevant for the authorization_code response type + if ([tokenResponse.request.grantType isEqual:OIDGrantTypeAuthorizationCode]) { + // OpenID Connect Core Section 3.1.3.7. rule #11 + // Validates the nonce. + NSString *nonce = authorizationResponse.request.nonce; + if (nonce && ![idToken.nonce isEqual:nonce]) { + NSError *invalidIDToken = + [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:@"Nonce mismatch"]; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; + } + } + + // OpenID Connect Core Section 3.1.3.7. rules #12 + // ACR is not directly supported by AppAuth. + + // OpenID Connect Core Section 3.1.3.7. rules #12 + // max_age is not directly supported by AppAuth. + } + + // Success + dispatch_async(dispatch_get_main_queue(), ^{ + callback(tokenResponse, nil); + }); + }] resume]; +} + + +#pragma mark - Registration Endpoint + ++ (void)performRegistrationRequest:(OIDRegistrationRequest *)request + completion:(OIDRegistrationCompletion)completion { + NSURLRequest *URLRequest = [request URLRequest]; + if (!URLRequest) { + // A problem occurred deserializing the response/JSON. + NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONSerializationError + underlyingError:nil + description:@"The registration request could not " + "be serialized as JSON."]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, returnedError); + }); + return; + } + + NSURLSession *session = [OIDURLSessionProvider session]; + [[session dataTaskWithRequest:URLRequest + completionHandler:^(NSData *_Nullable data, + NSURLResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + // A network error or server error occurred. + NSString *errorDescription = + [NSString stringWithFormat:@"Connection error making registration request to '%@': %@.", + URLRequest.URL, + error.localizedDescription]; + NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeNetworkError + underlyingError:error + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, returnedError); + }); + return; + } + + NSHTTPURLResponse *HTTPURLResponse = (NSHTTPURLResponse *) response; + + if (HTTPURLResponse.statusCode != 201 && HTTPURLResponse.statusCode != 200) { + // A server error occurred. + NSError *serverError = [OIDErrorUtilities HTTPErrorWithHTTPResponse:HTTPURLResponse + data:data]; + + // HTTP 400 may indicate an OpenID Connect Dynamic Client Registration 1.0 Section 3.3 error + // response, checks for that + if (HTTPURLResponse.statusCode == 400) { + NSError *jsonDeserializationError; + NSDictionary *> *json = + [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError]; + + // if the HTTP 400 response parses as JSON and has an 'error' key, it's an OAuth error + // these errors are special as they indicate a problem with the authorization grant + if (json[OIDOAuthErrorFieldError]) { + NSError *oauthError = + [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthRegistrationErrorDomain + OAuthResponse:json + underlyingError:serverError]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, oauthError); + }); + return; + } + } + + // not an OAuth error, just a generic server error + NSString *errorDescription = + [NSString stringWithFormat:@"Non-200/201 HTTP response (%d) making registration request " + "to '%@'.", + (int)HTTPURLResponse.statusCode, + URLRequest.URL]; + NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeServerError + underlyingError:serverError + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, returnedError); + }); + return; + } + + NSError *jsonDeserializationError; + NSDictionary *> *json = + [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonDeserializationError]; + if (jsonDeserializationError) { + // A problem occurred deserializing the response/JSON. + NSString *errorDescription = + [NSString stringWithFormat:@"JSON error parsing registration response: %@", + jsonDeserializationError.localizedDescription]; + NSError *returnedError = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError + underlyingError:jsonDeserializationError + description:errorDescription]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, returnedError); + }); + return; + } + + OIDRegistrationResponse *registrationResponse = + [[OIDRegistrationResponse alloc] initWithRequest:request + parameters:json]; + if (!registrationResponse) { + // A problem occurred constructing the registration response from the JSON. + NSError *returnedError = + [OIDErrorUtilities errorWithCode:OIDErrorCodeRegistrationResponseConstructionError + underlyingError:nil + description:@"Registration response invalid."]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, returnedError); + }); + return; + } + + // Success + dispatch_async(dispatch_get_main_queue(), ^{ + completion(registrationResponse, nil); + }); + }] resume]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.h new file mode 100644 index 00000000..39ea2d62 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.h @@ -0,0 +1,51 @@ +/*! @file OIDClientMetadataParameters.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Parameter name for the token endpoint authentication method. + */ +extern NSString *const OIDTokenEndpointAuthenticationMethodParam; + +/*! @brief Parameter name for the application type. + */ +extern NSString *const OIDApplicationTypeParam; + +/*! @brief Parameter name for the redirect URI values. + */ +extern NSString *const OIDRedirectURIsParam; + +/*! @brief Parameter name for the response type values. + */ +extern NSString *const OIDResponseTypesParam; + +/*! @brief Parameter name for the grant type values. + */ +extern NSString *const OIDGrantTypesParam; + +/*! @brief Parameter name for the subject type. + */ +extern NSString *const OIDSubjectTypeParam; + +/*! @brief Application type that indicates this client is a native (not a web) application. + */ +extern NSString *const OIDApplicationTypeNative; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.m new file mode 100644 index 00000000..79ad4676 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDClientMetadataParameters.m @@ -0,0 +1,33 @@ +/*! @file OIDClientMetadataParameters.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDClientMetadataParameters.h" + +NSString *const OIDTokenEndpointAuthenticationMethodParam = @"token_endpoint_auth_method"; + +NSString *const OIDApplicationTypeParam = @"application_type"; + +NSString *const OIDRedirectURIsParam = @"redirect_uris"; + +NSString *const OIDResponseTypesParam = @"response_types"; + +NSString *const OIDGrantTypesParam = @"grant_types"; + +NSString *const OIDSubjectTypeParam = @"subject_type"; + +NSString *const OIDApplicationTypeNative = @"native"; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDDefines.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDDefines.h new file mode 100644 index 00000000..8ff4f19b --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDDefines.h @@ -0,0 +1,51 @@ +/*! @file OIDDefines.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/*! @def OIDIsEqualIncludingNil(x, y) + @brief Returns YES if x and y are equal by reference or value. + @discussion NOTE: parameters may be evaluated multiple times. Be careful if using this check + with expressions - especially if the expressions have side effects. + @param x An object. + @param y An object. + */ +#define OIDIsEqualIncludingNil(x, y) (((x) == (y)) || [(x) isEqual:(y)]) + +/*! @def OID_UNAVAILABLE_USE_INITIALIZER(designatedInitializer) + @brief Provides a template implementation for init-family methods which have been marked as + NS_UNAVILABLE. Stops the compiler from giving a warning when it's the super class' + designated initializer, and gives callers useful feedback telling them what the + new designated initializer is. + @remarks Takes a SEL as a parameter instead of a string so that we get compiler warnings if the + designated intializer's signature changes. + @param designatedInitializer A SEL referencing the designated initializer. + */ +#define OID_UNAVAILABLE_USE_INITIALIZER(designatedInitializer) { \ + NSString *reason = [NSString stringWithFormat:@"Called: %@\nDesignated Initializer:%@", \ + NSStringFromSelector(_cmd), \ + NSStringFromSelector(designatedInitializer)]; \ + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." \ + reason:reason \ + userInfo:nil]; \ +} + +#ifdef _APPAUTHTRACE +# define AppAuthRequestTrace(fmt, ...) NSLog(fmt, ##__VA_ARGS__); +#else // _APPAUTHTRACE +# define AppAuthRequestTrace(...) +#endif // _APPAUTHTRACE + diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.h new file mode 100644 index 00000000..4087e9fa --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.h @@ -0,0 +1,107 @@ +/*! @file OIDEndSessionRequest.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "OIDExternalUserAgentRequest.h" + +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDEndSessionRequest : NSObject + + +/*! @brief The service's configuration. + @remarks This configuration specifies how to connect to a particular OAuth provider. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @brief The client's redirect URI. + @remarks post_logout_redirect_uri + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSURL *postLogoutRedirectURL; + +/*! @brief Previously issued ID Token passed to the end session endpoint as a hint about the End-User's current authenticated + session with the Client + @remarks id_token_hint + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSString *idTokenHint; + +/*! @brief An opaque value used by the client to maintain state between the request and callback. + @remarks state + @discussion If this value is not explicitly set, this library will automatically add state and + perform appropriate validation of the state in the authorization response. It is recommended + that the default implementation of this parameter be used wherever possible. Typically used + to prevent CSRF attacks, as recommended in RFC6819 Section 5.3.5. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @brief The client's additional authorization parameters. + @see https://tools.ietf.org/html/rfc6749#section-3.1 + */ +@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters; + +/*! @internal + @brief Unavailable. Please use @c initWithConfiguration:clientId:scopes:redirectURL:additionalParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Creates an authorization request with opinionated defaults (a secure @c state). + @param configuration The service's configuration. + @param idTokenHint The previously issued ID Token + @param postLogoutRedirectURL The client's post-logout redirect URI. + callback. + @param additionalParameters The client's additional authorization parameters. +*/ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Designated initializer. + @param configuration The service's configuration. + @param idTokenHint The previously issued ID Token + @param postLogoutRedirectURL The client's post-logout redirect URI. + @param state An opaque value used by the client to maintain state between the request and + callback. + @param additionalParameters The client's additional authorization parameters. + */ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + state:(NSString *)state + additionalParameters:(nullable NSDictionary *)additionalParameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Constructs the request URI by adding the request parameters to the query component of the + authorization endpoint URI using the "application/x-www-form-urlencoded" format. + @return A URL representing the authorization request. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +- (NSURL *)endSessionRequestURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.m new file mode 100644 index 00000000..1e9eb0e2 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionRequest.m @@ -0,0 +1,190 @@ +/*! @file OIDEndSessionRequest.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDEndSessionRequest.h" + +#import "OIDDefines.h" +#import "OIDTokenUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDURLQueryComponent.h" + +/*! @brief The key for the @c configuration property for @c NSSecureCoding + */ +static NSString *const kConfigurationKey = @"configuration"; + +/*! @brief Key used to encode the @c state property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief Key used to encode the @c postLogoutRedirectURL property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kPostLogoutRedirectURLKey = @"post_logout_redirect_uri"; + +/*! @brief Key used to encode the @c idTokenHint property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kIdTokenHintKey = @"id_token_hint"; + +/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +/*! @brief Number of random bytes generated for the @state. + */ +static NSUInteger const kStateSizeBytes = 32; + +/*! @brief Assertion text for missing end_session_endpoint. + */ +static NSString *const OIDMissingEndSessionEndpointMessage = +@"The service configuration is missing an end_session_endpoint."; + +@implementation OIDEndSessionRequest + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER( + @selector(initWithConfiguration: + idTokenHint: + postLogoutRedirectURL: + additionalParameters:) + ) + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + state:(NSString *)state + additionalParameters:(NSDictionary *)additionalParameters +{ + self = [super init]; + if (self) { + _configuration = [configuration copy]; + _idTokenHint = [idTokenHint copy]; + _postLogoutRedirectURL = [postLogoutRedirectURL copy]; + _state = [state copy]; + _additionalParameters = + [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES]; + } + return self; +} + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + additionalParameters:(NSDictionary *)additionalParameters +{ + return [self initWithConfiguration:configuration + idTokenHint:idTokenHint + postLogoutRedirectURL:postLogoutRedirectURL + state:[[self class] generateState] + additionalParameters:additionalParameters]; +} +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDServiceConfiguration *configuration = [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] forKey:kConfigurationKey]; + + NSString *idTokenHint = [aDecoder decodeObjectOfClass:[NSString class] forKey:kIdTokenHintKey]; + NSURL *postLogoutRedirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPostLogoutRedirectURLKey]; + NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey]; + NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ + [NSDictionary class], + [NSString class] + ]]; + NSDictionary *additionalParameters = [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses + forKey:kAdditionalParametersKey]; + + self = [self initWithConfiguration:configuration + idTokenHint:idTokenHint + postLogoutRedirectURL:postLogoutRedirectURL + state:state + additionalParameters:additionalParameters]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_configuration forKey:kConfigurationKey]; + [aCoder encodeObject:_idTokenHint forKey:kIdTokenHintKey]; + [aCoder encodeObject:_postLogoutRedirectURL forKey:kPostLogoutRedirectURLKey]; + [aCoder encodeObject:_state forKey:kStateKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, request: %@>", + NSStringFromClass([self class]), + (void *)self, + self.endSessionRequestURL]; +} + ++ (nullable NSString *)generateState { + return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; +} + +#pragma mark - OIDExternalUserAgentRequest + +- (NSURL*)externalUserAgentRequestURL { + return [self endSessionRequestURL]; +} + +- (NSString *)redirectScheme { + return [_postLogoutRedirectURL scheme]; +} + +#pragma mark - + +- (NSURL *)endSessionRequestURL { + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init]; + + // Add any additional parameters the client has specified. + [query addParameters:_additionalParameters]; + + // Add optional parameters, as applicable. + if (_idTokenHint) { + [query addParameter:kIdTokenHintKey value:_idTokenHint]; + } + + if (_postLogoutRedirectURL) { + [query addParameter:kPostLogoutRedirectURLKey value:_postLogoutRedirectURL.absoluteString]; + } + + if (_state) { + [query addParameter:kStateKey value:_state]; + } + + NSAssert(_configuration.endSessionEndpoint, OIDMissingEndSessionEndpointMessage); + + // Construct the URL + return [query URLByReplacingQueryInURL:_configuration.endSessionEndpoint]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.h new file mode 100644 index 00000000..ab69b930 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.h @@ -0,0 +1,64 @@ +/*! @file OIDEndSessionResponse.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDEndSessionRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents the response to an End Session request. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ + +@interface OIDEndSessionResponse : NSObject + +/*! @brief The request which was serviced. + */ +@property(nonatomic, readonly) OIDEndSessionRequest *request; + +/*! @brief REQUIRED if the "state" parameter was present in the client end-session request. The + exact value received from the client. + @remarks state + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @brief Additional parameters returned from the end session endpoint. + */ +@property(nonatomic, readonly, nullable) + NSDictionary *> *additionalParameters; + +/*! @internal + @brief Unavailable. Please use initWithParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Designated initializer. + @param request The serviced request. + @param parameters The decoded parameters returned from the End Session Endpoint. + @remarks Known parameters are extracted from the @c parameters parameter and the normative + properties are populated. Non-normative parameters are placed in the + @c #additionalParameters dictionary. + */ +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request + parameters:(NSDictionary *> *)parameters + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.m new file mode 100644 index 00000000..bedf0cd9 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDEndSessionResponse.m @@ -0,0 +1,118 @@ +/*! @file OIDEndSessionResponse.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDEndSessionResponse.h" + +#import "OIDDefines.h" +#import "OIDEndSessionRequest.h" +#import "OIDFieldMapping.h" + +/*! @brief The key for the @c state property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief Key used to encode the @c request property for @c NSSecureCoding + */ +static NSString *const kRequestKey = @"request"; + +/*! @brief Key used to encode the @c additionalParameters property for + @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +@implementation OIDEndSessionResponse + +#pragma mark - Initializers + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:)) + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request + parameters:(NSDictionary *> *)parameters { + self = [super init]; + if (self) { + _request = [request copy]; + NSDictionary *> *additionalParameters = + [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap] + parameters:parameters + instance:self]; + _additionalParameters = additionalParameters; + } + return self; +} + +/*! @brief Returns a mapping of incoming parameters to instance variables. + @return A mapping of incoming parameters to instance variables. + */ ++ (NSDictionary *)fieldMap { + static NSMutableDictionary *fieldMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fieldMap = [NSMutableDictionary dictionary]; + fieldMap[kStateKey] = + [[OIDFieldMapping alloc] initWithName:@"_state" type:[NSString class]]; + }); + return fieldMap; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDEndSessionRequest *request = + [aDecoder decodeObjectOfClass:[OIDEndSessionRequest class] forKey:kRequestKey]; + self = [self initWithRequest:request parameters:@{ }]; + if (self) { + [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self]; + _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes] + forKey:kAdditionalParametersKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_request forKey:kRequestKey]; + [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, state: \"%@\", " + "additionalParameters: %@, request: %@>", + NSStringFromClass([self class]), + (void *)self, + _state, + _additionalParameters, + _request]; +} +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.h new file mode 100644 index 00000000..5131f0ad --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.h @@ -0,0 +1,393 @@ +/*! @file OIDError.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief The error domain for all NSErrors returned from the AppAuth library. + */ +extern NSString *const OIDGeneralErrorDomain; + +/*! @brief The error domain for OAuth specific errors on the authorization endpoint. + @discussion This error domain is used when the server responds to an authorization request + with an explicit OAuth error, as defined by RFC6749 Section 4.1.2.1. If the authorization + response is invalid and not explicitly an error response, another error domain will be used. + The error response parameter dictionary is available in the + \NSError_userInfo dictionary using the @c ::OIDOAuthErrorResponseErrorKey key. + The \NSError_code will be one of the @c ::OIDErrorCodeOAuthAuthorization enum values. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ +extern NSString *const OIDOAuthAuthorizationErrorDomain; + +/*! @brief The error domain for OAuth specific errors on the token endpoint. + @discussion This error domain is used when the server responds with HTTP 400 and an OAuth error, + as defined RFC6749 Section 5.2. If an HTTP 400 response does not parse as an OAuth error + (i.e. no 'error' field is present or the JSON is invalid), another error domain will be + used. The entire OAuth error response dictionary is available in the \NSError_userInfo + dictionary using the @c ::OIDOAuthErrorResponseErrorKey key. Unlike transient network + errors, errors in this domain invalidate the authentication state, and either indicate a + client error or require user interaction (i.e. reauthentication) to resolve. + The \NSError_code will be one of the @c ::OIDErrorCodeOAuthToken enum values. + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +extern NSString *const OIDOAuthTokenErrorDomain; + +/*! @brief The error domain for dynamic client registration errors. + @discussion This error domain is used when the server responds with HTTP 400 and an OAuth error, + as defined in OpenID Connect Dynamic Client Registration 1.0 Section 3.3. If an HTTP 400 + response does not parse as an OAuth error (i.e. no 'error' field is present or the JSON is + invalid), another error domain will be used. The entire OAuth error response dictionary is + available in the \NSError_userInfo dictionary using the @c ::OIDOAuthErrorResponseErrorKey + key. Unlike transient network errors, errors in this domain invalidate the authentication + state, and indicates a client error. + The \NSError_code will be one of the @c ::OIDErrorCodeOAuthToken enum values. + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ +extern NSString *const OIDOAuthRegistrationErrorDomain; + +/*! @brief The error domain for authorization errors encountered out of band on the resource server. + */ +extern NSString *const OIDResourceServerAuthorizationErrorDomain; + +/*! @brief An error domain representing received HTTP errors. + */ +extern NSString *const OIDHTTPErrorDomain; + +/*! @brief An error key for the original OAuth error response (if any). + */ +extern NSString *const OIDOAuthErrorResponseErrorKey; + +/*! @brief The key of the 'error' response field in a RFC6749 Section 5.2 response. + @remark error + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +extern NSString *const OIDOAuthErrorFieldError; + +/*! @brief The key of the 'error_description' response field in a RFC6749 Section 5.2 response. + @remark error_description + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +extern NSString *const OIDOAuthErrorFieldErrorDescription; + +/*! @brief The key of the 'error_uri' response field in a RFC6749 Section 5.2 response. + @remark error_uri + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +extern NSString *const OIDOAuthErrorFieldErrorURI; + +/*! @brief The various error codes returned from the AppAuth library. + */ +typedef NS_ENUM(NSInteger, OIDErrorCode) { + /*! @brief Indicates a problem parsing an OpenID Connect Service Discovery document. + */ + OIDErrorCodeInvalidDiscoveryDocument = -2, + + /*! @brief Indicates the user manually canceled the OAuth authorization code flow. + */ + OIDErrorCodeUserCanceledAuthorizationFlow = -3, + + /*! @brief Indicates an OAuth authorization flow was programmatically cancelled. + */ + OIDErrorCodeProgramCanceledAuthorizationFlow = -4, + + /*! @brief Indicates a network error or server error occurred. + */ + OIDErrorCodeNetworkError = -5, + + /*! @brief Indicates a server error occurred. + */ + OIDErrorCodeServerError = -6, + + /*! @brief Indicates a problem occurred deserializing the response/JSON. + */ + OIDErrorCodeJSONDeserializationError = -7, + + /*! @brief Indicates a problem occurred constructing the token response from the JSON. + */ + OIDErrorCodeTokenResponseConstructionError = -8, + + /*! @brief @c UIApplication.openURL: returned NO when attempting to open the authorization + request in mobile Safari. + */ + OIDErrorCodeSafariOpenError = -9, + + /*! @brief @c NSWorkspace.openURL returned NO when attempting to open the authorization + request in the default browser. + */ + OIDErrorCodeBrowserOpenError = -10, + + /*! @brief Indicates a problem when trying to refresh the tokens. + */ + OIDErrorCodeTokenRefreshError = -11, + + /*! @brief Indicates a problem occurred constructing the registration response from the JSON. + */ + OIDErrorCodeRegistrationResponseConstructionError = -12, + + /*! @brief Indicates a problem occurred deserializing the response/JSON. + */ + OIDErrorCodeJSONSerializationError = -13, + + /*! @brief The ID Token did not parse. + */ + OIDErrorCodeIDTokenParsingError = -14, + + /*! @brief The ID Token did not pass validation (e.g. issuer, audience checks). + */ + OIDErrorCodeIDTokenFailedValidationError = -15, +}; + +/*! @brief Enum of all possible OAuth error codes as defined by RFC6749 + @discussion Used by @c ::OIDErrorCodeOAuthAuthorization and @c ::OIDErrorCodeOAuthToken + which define endpoint-specific subsets of OAuth codes. Those enum types are down-castable + to this one. + @see https://tools.ietf.org/html/rfc6749#section-11.4 + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +typedef NS_ENUM(NSInteger, OIDErrorCodeOAuth) { + + /*! @remarks invalid_request + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthInvalidRequest = -2, + + /*! @remarks unauthorized_client + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthUnauthorizedClient = -3, + + /*! @remarks access_denied + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAccessDenied = -4, + + /*! @remarks unsupported_response_type + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthUnsupportedResponseType = -5, + + /*! @remarks invalid_scope + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthInvalidScope = -6, + + /*! @remarks server_error + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthServerError = -7, + + /*! @remarks temporarily_unavailable + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthTemporarilyUnavailable = -8, + + /*! @remarks invalid_client + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthInvalidClient = -9, + + /*! @remarks invalid_grant + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthInvalidGrant = -10, + + /*! @remarks unsupported_grant_type + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthUnsupportedGrantType = -11, + + /*! @remarks invalid_redirect_uri + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ + OIDErrorCodeOAuthInvalidRedirectURI = -12, + + /*! @remarks invalid_client_metadata + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ + OIDErrorCodeOAuthInvalidClientMetadata = -13, + + /*! @brief An authorization error occurring on the client rather than the server. For example, + due to a state mismatch or misconfiguration. Should be treated as an unrecoverable + authorization error. + */ + OIDErrorCodeOAuthClientError = -0xEFFF, + + /*! @brief An OAuth error not known to this library + @discussion Indicates an OAuth error as per RFC6749, but the error code was not in our + list. It could be a custom error code, or one from an OAuth extension. See the "error" key + of the \NSError_userInfo property. Such errors are assumed to invalidate the + authentication state + */ + OIDErrorCodeOAuthOther = -0xF000, +}; + +/*! @brief The error codes for the @c ::OIDOAuthAuthorizationErrorDomain error domain + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ +typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthAuthorization) { + /*! @remarks invalid_request + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationInvalidRequest = OIDErrorCodeOAuthInvalidRequest, + + /*! @remarks unauthorized_client + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationUnauthorizedClient = OIDErrorCodeOAuthUnauthorizedClient, + + /*! @remarks access_denied + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationAccessDenied = + OIDErrorCodeOAuthAccessDenied, + + /*! @remarks unsupported_response_type + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationUnsupportedResponseType = + OIDErrorCodeOAuthUnsupportedResponseType, + + /*! @brief Indicates a network error or server error occurred. + @remarks invalid_scope + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationAuthorizationInvalidScope = OIDErrorCodeOAuthInvalidScope, + + /*! @brief Indicates a server error occurred. + @remarks server_error + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationServerError = OIDErrorCodeOAuthServerError, + + /*! @remarks temporarily_unavailable + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationTemporarilyUnavailable = OIDErrorCodeOAuthTemporarilyUnavailable, + + /*! @brief An authorization error occurring on the client rather than the server. For example, + due to a state mismatch or client misconfiguration. Should be treated as an unrecoverable + authorization error. + */ + OIDErrorCodeOAuthAuthorizationClientError = OIDErrorCodeOAuthClientError, + + /*! @brief An authorization OAuth error not known to this library + @discussion this indicates an OAuth error as per RFC6749, but the error code was not in our + list. It could be a custom error code, or one from an OAuth extension. See the "error" key + of the \NSError_userInfo property. We assume such errors are not transient. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + */ + OIDErrorCodeOAuthAuthorizationOther = OIDErrorCodeOAuthOther, +}; + + +/*! @brief The error codes for the @c ::OIDOAuthTokenErrorDomain error domain + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ +typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthToken) { + /*! @remarks invalid_request + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenInvalidRequest = OIDErrorCodeOAuthInvalidRequest, + + /*! @remarks invalid_client + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenInvalidClient = OIDErrorCodeOAuthInvalidClient, + + /*! @remarks invalid_grant + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenInvalidGrant = OIDErrorCodeOAuthInvalidGrant, + + /*! @remarks unauthorized_client + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenUnauthorizedClient = OIDErrorCodeOAuthUnauthorizedClient, + + /*! @remarks unsupported_grant_type + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenUnsupportedGrantType = OIDErrorCodeOAuthUnsupportedGrantType, + + /*! @remarks invalid_scope + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenInvalidScope = OIDErrorCodeOAuthInvalidScope, + + /*! @brief An unrecoverable token error occurring on the client rather than the server. + */ + OIDErrorCodeOAuthTokenClientError = OIDErrorCodeOAuthClientError, + + /*! @brief A token endpoint OAuth error not known to this library + @discussion this indicates an OAuth error as per RFC6749, but the error code was not in our + list. It could be a custom error code, or one from an OAuth extension. See the "error" key + of the \NSError_userInfo property. We assume such errors are not transient. + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthTokenOther = OIDErrorCodeOAuthOther, +}; + +/*! @brief The error codes for the @c ::OIDOAuthRegistrationErrorDomain error domain + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ +typedef NS_ENUM(NSInteger, OIDErrorCodeOAuthRegistration) { + /*! @remarks invalid_request + @see http://tools.ietf.org/html/rfc6750#section-3.1 + */ + OIDErrorCodeOAuthRegistrationInvalidRequest = OIDErrorCodeOAuthInvalidRequest, + + /*! @remarks invalid_redirect_uri + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ + OIDErrorCodeOAuthRegistrationInvalidRedirectURI = OIDErrorCodeOAuthInvalidRedirectURI, + + /*! @remarks invalid_client_metadata + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError + */ + OIDErrorCodeOAuthRegistrationInvalidClientMetadata = OIDErrorCodeOAuthInvalidClientMetadata, + + /*! @brief An unrecoverable token error occurring on the client rather than the server. + */ + OIDErrorCodeOAuthRegistrationClientError = OIDErrorCodeOAuthClientError, + + /*! @brief A registration endpoint OAuth error not known to this library + @discussion this indicates an OAuth error, but the error code was not in our + list. It could be a custom error code, or one from an OAuth extension. See the "error" key + of the \NSError_userInfo property. We assume such errors are not transient. + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ + OIDErrorCodeOAuthRegistrationOther = OIDErrorCodeOAuthOther, +}; + + +/*! @brief The exception text for the exception which occurs when a + @c OIDExternalUserAgentSession receives a message after it has already completed. + */ +extern NSString *const OIDOAuthExceptionInvalidAuthorizationFlow; + +/*! @brief The text for the exception which occurs when a Token Request is constructed + with a null redirectURL for a grant_type that requires a nonnull Redirect + */ +extern NSString *const OIDOAuthExceptionInvalidTokenRequestNullRedirectURL; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.m new file mode 100644 index 00000000..87c8623e --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDError.m @@ -0,0 +1,45 @@ +/*! @file OIDError.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDError.h" + +NSString *const OIDGeneralErrorDomain = @"org.openid.appauth.general"; + +NSString *const OIDOAuthTokenErrorDomain = @"org.openid.appauth.oauth_token"; + +NSString *const OIDOAuthAuthorizationErrorDomain = @"org.openid.appauth.oauth_authorization"; + +NSString *const OIDOAuthRegistrationErrorDomain = @"org.openid.appauth.oauth_registration"; + +NSString *const OIDResourceServerAuthorizationErrorDomain = @"org.openid.appauth.resourceserver"; + +NSString *const OIDHTTPErrorDomain = @"org.openid.appauth.remote-http"; + +NSString *const OIDOAuthExceptionInvalidAuthorizationFlow = @"An OAuth redirect was sent to a " + "OIDExternalUserAgentSession after it already completed."; + +NSString *const OIDOAuthExceptionInvalidTokenRequestNullRedirectURL = @"A OIDTokenRequest was " + "created with a grant_type that requires a redirectURL, but a null redirectURL was given"; + +NSString *const OIDOAuthErrorResponseErrorKey = @"OIDOAuthErrorResponseErrorKey"; + +NSString *const OIDOAuthErrorFieldError = @"error"; + +NSString *const OIDOAuthErrorFieldErrorDescription = @"error_description"; + +NSString *const OIDOAuthErrorFieldErrorURI = @"error_uri"; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.h new file mode 100644 index 00000000..3380f6fe --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.h @@ -0,0 +1,107 @@ +/*! @file OIDErrorUtilities.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "OIDError.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Convenience methods for creating standardized \NSError instances. + */ +@interface OIDErrorUtilities : NSObject + +/*! @brief Creates a standard \NSError from an @c ::OIDErrorCode and custom user info. + Automatically populates the localized error description. + @param code The error code. + @param underlyingError The underlying error which occurred, if applicable. + @param description A custom description, if applicable. + @return An \NSError representing the error code. + */ ++ (NSError *)errorWithCode:(OIDErrorCode)code + underlyingError:(nullable NSError *)underlyingError + description:(nullable NSString *)description; + +/*! @brief Creates a standard \NSError from an @c ::OIDErrorCode and custom user info. + Automatically populates the localized error description. + @param OAuthErrorDomain The OAuth error domain. Must be @c ::OIDOAuthAuthorizationErrorDomain or + @c ::OIDOAuthTokenErrorDomain. + @param errorResponse The dictionary from an OAuth error response (as per RFC6749 Section 5.2). + @param underlyingError The underlying error which occurred, if applicable. + @return An \NSError representing the OAuth error. + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ ++ (NSError *)OAuthErrorWithDomain:(NSString *)OAuthErrorDomain + OAuthResponse:(NSDictionary *)errorResponse + underlyingError:(nullable NSError *)underlyingError; + +/*! @brief Creates a \NSError indicating that the resource server responded with an authorization + error. + @param code Your error code. + @param errorResponse The resource server error response, if any. + @param underlyingError The underlying error which occurred, if applicable. + @return An \NSError representing the authorization error from the resource server. + */ ++ (NSError *)resourceServerAuthorizationErrorWithCode:(NSInteger)code + errorResponse:(nullable NSDictionary *)errorResponse + underlyingError:(nullable NSError *)underlyingError; + + +/*! @brief Creates a standard \NSError from an \NSHTTPURLResponse. Automatically + populates the localized error description with the response data associated with the + \NSHTTPURLResponse, if available. + @param HTTPURLResponse The response which indicates an error occurred. + @param data The response data associated with the response which should be converted to an + @c NSString assuming a UTF-8 encoding, if available. + @return An \NSError representing the error. + */ ++ (NSError *)HTTPErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPURLResponse + data:(nullable NSData *)data; + +/*! @brief Raises an exception with the given name as both the name, and the message. + @param name The name of the exception. + */ ++ (void)raiseException:(NSString *)name; + +/*! @brief Raises an exception with the given name and message. + @param name The name of the exception. + @param message The message of the exception. + */ ++ (void)raiseException:(NSString *)name message:(NSString *)message; + +/*! @brief Converts an OAuth error code into an @c ::OIDErrorCodeOAuth error code. + @param errorCode The OAuth error code. + @discussion Returns @c ::OIDErrorCodeOAuthOther if the string is not in AppAuth's list. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ ++ (OIDErrorCodeOAuth)OAuthErrorCodeFromString:(NSString *)errorCode; + +/*! @brief Returns true if the given error domain is an OAuth error domain. + @param errorDomain The error domain to test. + @discussion An OAuth error domain is used for errors returned per RFC6749 sections 4.1.2.1 and + 5.2. Other errors, such as network errors can also occur but they will not have an OAuth + error domain. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2.1 + @see https://tools.ietf.org/html/rfc6749#section-5.2 + */ ++ (BOOL)isOAuthErrorDomain:(NSString*)errorDomain; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.m new file mode 100644 index 00000000..3b3c0607 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDErrorUtilities.m @@ -0,0 +1,172 @@ +/*! @file OIDErrorUtilities.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDErrorUtilities.h" + +@implementation OIDErrorUtilities + ++ (NSError *)errorWithCode:(OIDErrorCode)code + underlyingError:(NSError *)underlyingError + description:(NSString *)description { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + if (description) { + userInfo[NSLocalizedDescriptionKey] = description; + } + // TODO: Populate localized description based on code. + NSError *error = [NSError errorWithDomain:OIDGeneralErrorDomain + code:code + userInfo:userInfo]; + return error; +} + ++ (BOOL)isOAuthErrorDomain:(NSString *)errorDomain { + return errorDomain == OIDOAuthRegistrationErrorDomain + || errorDomain == OIDOAuthAuthorizationErrorDomain + || errorDomain == OIDOAuthTokenErrorDomain; +} + ++ (NSError *)resourceServerAuthorizationErrorWithCode:(NSInteger)code + errorResponse:(nullable NSDictionary *)errorResponse + underlyingError:(nullable NSError *)underlyingError { + // builds the userInfo dictionary with the full OAuth response and other information + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (errorResponse) { + userInfo[OIDOAuthErrorResponseErrorKey] = errorResponse; + } + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + NSError *error = [NSError errorWithDomain:OIDResourceServerAuthorizationErrorDomain + code:code + userInfo:userInfo]; + return error; +} + ++ (NSError *)OAuthErrorWithDomain:(NSString *)oAuthErrorDomain + OAuthResponse:(NSDictionary *)errorResponse + underlyingError:(NSError *)underlyingError { + // not a valid OAuth error + if (![self isOAuthErrorDomain:oAuthErrorDomain] + || !errorResponse + || !errorResponse[OIDOAuthErrorFieldError] + || ![errorResponse[OIDOAuthErrorFieldError] isKindOfClass:[NSString class]]) { + return [[self class] errorWithCode:OIDErrorCodeNetworkError + underlyingError:underlyingError + description:underlyingError.localizedDescription]; + } + + // builds the userInfo dictionary with the full OAuth response and other information + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + userInfo[OIDOAuthErrorResponseErrorKey] = errorResponse; + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + + NSString *oauthErrorCodeString = errorResponse[OIDOAuthErrorFieldError]; + NSString *oauthErrorMessage = nil; + if ([errorResponse[OIDOAuthErrorFieldErrorDescription] isKindOfClass:[NSString class]]) { + oauthErrorMessage = errorResponse[OIDOAuthErrorFieldErrorDescription]; + } else { + oauthErrorMessage = [errorResponse[OIDOAuthErrorFieldErrorDescription] description]; + } + NSString *oauthErrorURI = nil; + if ([errorResponse[OIDOAuthErrorFieldErrorURI] isKindOfClass:[NSString class]]) { + oauthErrorURI = errorResponse[OIDOAuthErrorFieldErrorURI]; + } else { + oauthErrorURI = [errorResponse[OIDOAuthErrorFieldErrorURI] description]; + } + + // builds the error description, using the information supplied by the server if possible + NSMutableString *description = [NSMutableString string]; + [description appendString:oauthErrorCodeString]; + if (oauthErrorMessage) { + [description appendString:@": "]; + [description appendString:oauthErrorMessage]; + } + if (oauthErrorURI) { + if ([description length] > 0) { + [description appendString:@" - "]; + } + [description appendString:oauthErrorURI]; + } + if ([description length] == 0) { + // backup description + [description appendFormat:@"OAuth error: %@ - https://tools.ietf.org/html/rfc6749#section-5.2", + oauthErrorCodeString]; + } + userInfo[NSLocalizedDescriptionKey] = description; + + // looks up the error code based on the "error" response param + OIDErrorCodeOAuth code = [[self class] OAuthErrorCodeFromString:oauthErrorCodeString]; + + NSError *error = [NSError errorWithDomain:oAuthErrorDomain + code:code + userInfo:userInfo]; + return error; +} + ++ (NSError *)HTTPErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPURLResponse + data:(nullable NSData *)data { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (data) { + NSString *serverResponse = + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (serverResponse) { + userInfo[NSLocalizedDescriptionKey] = serverResponse; + } + } + NSError *serverError = + [NSError errorWithDomain:OIDHTTPErrorDomain + code:HTTPURLResponse.statusCode + userInfo:userInfo]; + return serverError; +} + ++ (OIDErrorCodeOAuth)OAuthErrorCodeFromString:(NSString *)errorCode { + NSDictionary *errorCodes = @{ + @"invalid_request": @(OIDErrorCodeOAuthInvalidRequest), + @"unauthorized_client": @(OIDErrorCodeOAuthUnauthorizedClient), + @"access_denied": @(OIDErrorCodeOAuthAccessDenied), + @"unsupported_response_type": @(OIDErrorCodeOAuthUnsupportedResponseType), + @"invalid_scope": @(OIDErrorCodeOAuthInvalidScope), + @"server_error": @(OIDErrorCodeOAuthServerError), + @"temporarily_unavailable": @(OIDErrorCodeOAuthTemporarilyUnavailable), + @"invalid_client": @(OIDErrorCodeOAuthInvalidClient), + @"invalid_grant": @(OIDErrorCodeOAuthInvalidGrant), + @"unsupported_grant_type": @(OIDErrorCodeOAuthUnsupportedGrantType), + }; + NSNumber *code = errorCodes[errorCode]; + if (code) { + return [code integerValue]; + } else { + return OIDErrorCodeOAuthOther; + } +} + ++ (void)raiseException:(NSString *)name { + [[self class] raiseException:name message:name]; +} + ++ (void)raiseException:(NSString *)name message:(NSString *)message { + [NSException raise:name format:@"%@", message]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgent.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgent.h new file mode 100644 index 00000000..c4eb0a90 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgent.h @@ -0,0 +1,53 @@ +/*! @file OIDExternalUserAgent.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@protocol OIDExternalUserAgentSession; +@protocol OIDExternalUserAgentRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @protocol OIDExternalUserAgent + @brief An external user-agent UI that presents displays the request to the user. Clients may + provide custom implementations of an external user-agent to customize the way the requests + are presented to the end user. + */ +@protocol OIDExternalUserAgent + +/*! @brief Presents the request in the external user-agent. + @param request The request to be presented in the external user-agent. + @param session The @c OIDExternalUserAgentSession instance that initiates presenting the UI. + Concrete implementations of a @c OIDExternalUserAgent may call + resumeExternalUserAgentFlowWithURL or failExternalUserAgentFlowWithError on session to either + resume or fail the request. + @return YES If the request UI was successfully presented to the user. + */ +- (BOOL)presentExternalUserAgentRequest:(id )request + session:(id)session; + +/*! @brief Dimisses the external user-agent and calls completion when the dismiss operation ends. + @param animated Whether or not the dismiss operation should be animated. + @remarks Has no effect if no UI is presented. + @param completion The block to be called when the dismiss operations ends + */ +- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentRequest.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentRequest.h new file mode 100644 index 00000000..8ea40cb6 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentRequest.h @@ -0,0 +1,37 @@ +/*! @file OIDExternalUserAgent.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +/*! @protocol OIDExternalUserAgent + @brief An interface that any external user-agent request may implement to use the + @c OIDExternalUserAgent flow. + */ +@protocol OIDExternalUserAgentRequest + +/*! @brief Method to create and return the complete request URL instance. + @return A @c NSURL instance which contains the URL to be opened in an external UI (i.e. browser) + */ +- (NSURL*)externalUserAgentRequestURL; + +/*! @brief If this external user-agent request has a redirect URL, this should return its scheme. + Since some external requests have optional callbacks (such as the end session endpoint), the + return value of this method is nullable. + @return A @c NSString instance that contains the scheme of a callback url, or nil if there is + no callback url for this request. + */ +- (NSString*)redirectScheme; +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentSession.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentSession.h new file mode 100644 index 00000000..3b886a6c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDExternalUserAgentSession.h @@ -0,0 +1,65 @@ +/*! @file OIDExternalUserAgentSession.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents an in-flight external user-agent session. + */ +@protocol OIDExternalUserAgentSession + +/*! @brief Cancels the code flow session, invoking the request's callback with a cancelled error. + @remarks Has no effect if called more than once, or after a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message was received. + Will cause an error with code: @c ::OIDErrorCodeProgramCanceledAuthorizationFlow to be + passed to the @c callback block passed to + @c OIDAuthorizationService.presentAuthorizationRequest:presentingViewController:callback: + */ +- (void)cancel; + +/*! @brief Cancels the code flow session, invoking the request's callback with a cancelled error. + @remarks Has no effect if called more than once, or after a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message was received. + Will cause an error with code: @c ::OIDErrorCodeProgramCanceledAuthorizationFlow to be + passed to the @c callback block passed to + @c OIDAuthorizationService.presentAuthorizationRequest:presentingViewController:callback: + @param completion The block to be called when the cancel operation ends + */ +- (void)cancelWithCompletion:(nullable void (^)(void))completion; + +/*! @brief Clients should call this method with the result of the external user-agent code flow if + it becomes available. + @param URL The redirect URL invoked by the server. + @discussion When the URL represented a valid response, implementations should clean up any + left-over UI state from the request, for example by closing the + \SFSafariViewController or loopback HTTP listener if those were used. The completion block + of the pending request should then be invoked. + @remarks Has no effect if called more than once, or after a @c cancel message was received. + @return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise. + */ +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL; + +/*! @brief @c OIDExternalUserAgent or clients should call this method when the + external user-agent flow failed with a non-OAuth error. + @param error The error that is the reason for the failure of this external flow. + @remarks Has no effect if called more than once, or after a @c cancel message was received. + */ +- (void)failExternalUserAgentFlowWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.h new file mode 100644 index 00000000..f0a56fef --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.h @@ -0,0 +1,126 @@ +/*! @file OIDFieldMapping.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents a function which transforms incoming source values into instance variable + values. + */ +typedef _Nullable id(^OIDFieldMappingConversionFunction)(NSObject *_Nullable value); + +/*! @brief Describes the mapping of a key/value pair to an iVar with an optional conversion + function. + */ +@interface OIDFieldMapping : NSObject + +/*! @brief The name of the instance variable the field should be mapped to. + */ +@property(nonatomic, readonly) NSString *name; + +/*! @brief The type of the instance variable. + */ +@property(nonatomic, readonly) Class expectedType; + +/*! @brief An optional conversion function which specifies a transform from the incoming data to the + instance variable value. + */ +@property(nonatomic, readonly, nullable) OIDFieldMappingConversionFunction conversion; + +/*! @internal + @brief Unavailable. Please use initWithName:type:conversion:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief The designated initializer. + @param name The name of the instance variable the field should be mapped to. + @param type The type of the instance variable. + @param conversion An optional conversion function which specifies a transform from the incoming + data to the instance variable value. Used during the process performed by + @c OIDFieldMapping.remainingParametersWithMap:parameters:instance: but not during + encoding/decoding, since the encoded and decoded values should already be of the type + specified by the @c type parameter. + */ +- (instancetype)initWithName:(NSString *)name + type:(Class)type + conversion:(nullable OIDFieldMappingConversionFunction)conversion + NS_DESIGNATED_INITIALIZER; + +/*! @brief A convenience initializer. + @param name The name of the instance variable the field should be mapped to. + @param type The type of the instance variable. + */ +- (instancetype)initWithName:(NSString *)name + type:(Class)type; + +/*! @brief Performs a mapping of key/value pairs in an incoming parameters dictionary to instance + variables, returning a dictionary of parameter key/values which didn't map to instance + variables. + @param map A mapping of incoming keys to instance variables. + @param parameters Incoming key value pairs to map to an instance's variables. + @param instance The instance whose variables should be set based on the mapping. + @return A dictionary of parameter key/values which didn't map to instance variables. + */ ++ (NSDictionary *> *)remainingParametersWithMap: + (NSDictionary *)map + parameters:(NSDictionary *> *)parameters + instance:(id)instance; + +/*! @brief This helper method for @c NSCoding implementations performs a serialization of fields + defined in a field mapping. + @param aCoder An @c NSCoder instance to serialize instance variable values to. + @param map A mapping of keys to instance variables. + @param instance The instance whose variables should be serialized based on the mapping. + */ ++ (void)encodeWithCoder:(NSCoder *)aCoder + map:(NSDictionary *)map + instance:(id)instance; + +/*! @brief This helper method for @c NSCoding implementations performs a deserialization of + fields defined in a field mapping. + @param aCoder An @c NSCoder instance from which to deserialize instance variable values from. + @param map A mapping of keys to instance variables. + @param instance The instance whose variables should be deserialized based on the mapping. + */ ++ (void)decodeWithCoder:(NSCoder *)aCoder + map:(NSDictionary *)map + instance:(id)instance; + +/*! @brief Returns an @c NSSet of classes suitable for deserializing JSON content in an + @c NSSecureCoding context. + */ ++ (NSSet *)JSONTypes; + +/*! @brief Returns a function for converting an @c NSString to an @c NSURL. + */ ++ (OIDFieldMappingConversionFunction)URLConversion; + +/*! @brief Returns a function for converting an @c NSNumber number of seconds from now to an + @c NSDate. + */ ++ (OIDFieldMappingConversionFunction)dateSinceNowConversion; + +/*! @brief Returns a function for converting an @c NSNumber representing a unix time stamp to an + @c NSDate. + */ ++ (OIDFieldMappingConversionFunction)dateEpochConversion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.m new file mode 100644 index 00000000..f8436560 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDFieldMapping.m @@ -0,0 +1,132 @@ +/*! @file OIDFieldMapping.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDFieldMapping.h" + +#import "OIDDefines.h" + +@implementation OIDFieldMapping + +- (nonnull instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithName:type:conversion:)) + +- (instancetype)initWithName:(NSString *)name + type:(Class)type { + return [self initWithName:name type:type conversion:nil]; +} + +- (instancetype)initWithName:(NSString *)name + type:(Class)type + conversion:(nullable OIDFieldMappingConversionFunction)conversion { + self = [super init]; + if (self) { + _name = [name copy]; + _expectedType = type; + _conversion = conversion; + } + return self; +} + ++ (NSDictionary *> *)remainingParametersWithMap: + (NSDictionary *)map + parameters:(NSDictionary *> *)parameters + instance:(id)instance { + NSMutableDictionary *additionalParameters = [NSMutableDictionary dictionary]; + for (NSString *key in parameters) { + NSObject *value = [parameters[key] copy]; + OIDFieldMapping *mapping = map[key]; + // If the field doesn't appear in the mapping, we add it to the additional parameters + // dictionary. + if (!mapping) { + additionalParameters[key] = value; + continue; + } + // If the field mapping specifies a conversion function, apply the conversion to the value. + if (mapping.conversion) { + value = mapping.conversion(value); + } + // Check the type of the value and make sure it matches the type we expected. If it doesn't we + // add the value to the additional parameters dictionary but don't assign the instance variable. + if (![value isKindOfClass:mapping.expectedType]) { + additionalParameters[key] = value; + continue; + } + // Assign the instance variable. + [instance setValue:value forKey:mapping.name]; + } + return additionalParameters; +} + ++ (void)encodeWithCoder:(NSCoder *)aCoder + map:(NSDictionary *)map + instance:(id)instance { + for (NSString *key in map) { + id value = [instance valueForKey:map[key].name]; + [aCoder encodeObject:value forKey:key]; + } +} + ++ (void)decodeWithCoder:(NSCoder *)aCoder + map:(NSDictionary *)map + instance:(id)instance { + for (NSString *key in map) { + OIDFieldMapping *mapping = map[key]; + id value = [aCoder decodeObjectOfClass:mapping.expectedType forKey:key]; + [instance setValue:value forKey:mapping.name]; + } +} + ++ (NSSet *)JSONTypes { + return [NSSet setWithArray:@[ + [NSDictionary class], + [NSArray class], + [NSString class], + [NSNumber class] + ]]; +} + ++ (OIDFieldMappingConversionFunction)URLConversion { + return ^id _Nullable(NSObject *_Nullable value) { + if ([value isKindOfClass:[NSString class]]) { + return [NSURL URLWithString:(NSString *)value]; + } + return value; + }; +} + ++ (OIDFieldMappingConversionFunction)dateSinceNowConversion { + return ^id _Nullable(NSObject *_Nullable value) { + if (![value isKindOfClass:[NSNumber class]]) { + return value; + } + NSNumber *valueAsNumber = (NSNumber *)value; + return [NSDate dateWithTimeIntervalSinceNow:[valueAsNumber longLongValue]]; + }; +} + ++ (OIDFieldMappingConversionFunction)dateEpochConversion { + return ^id _Nullable(NSObject *_Nullable value) { + if (![value isKindOfClass:[NSNumber class]]) { + return value; + } + NSNumber *valueAsNumber = (NSNumber *) value; + return [NSDate dateWithTimeIntervalSince1970:[valueAsNumber longLongValue]]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.h new file mode 100644 index 00000000..6e650047 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.h @@ -0,0 +1,40 @@ +/*! @file OIDGrantTypes.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +/*! @brief For exchanging an authorization code for an access token. + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +extern NSString *const OIDGrantTypeAuthorizationCode; + +/*! @brief For refreshing an access token with a refresh token. + @see https://tools.ietf.org/html/rfc6749#section-6 + */ +extern NSString *const OIDGrantTypeRefreshToken; + +/*! @brief For obtaining an access token with a username and password. + @see https://tools.ietf.org/html/rfc6749#section-4.3.2 + */ +extern NSString *const OIDGrantTypePassword; + +/*! @brief For obtaining an access token from the token endpoint using client credentials. + @see https://tools.ietf.org/html/rfc6749#section-3.2.1 + @see https://tools.ietf.org/html/rfc6749#section-4.4.2 + */ +extern NSString *const OIDGrantTypeClientCredentials; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.m new file mode 100644 index 00000000..2b193437 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDGrantTypes.m @@ -0,0 +1,27 @@ +/*! @file OIDGrantTypes.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDGrantTypes.h" + +NSString *const OIDGrantTypeAuthorizationCode = @"authorization_code"; + +NSString *const OIDGrantTypeRefreshToken = @"refresh_token"; + +NSString *const OIDGrantTypePassword = @"password"; + +NSString *const OIDGrantTypeClientCredentials = @"client_credentials"; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.h new file mode 100644 index 00000000..6fe84d7f --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.h @@ -0,0 +1,91 @@ +/*! @file OIDIDToken.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief A convenience class that parses an ID Token and extracts the claims _but does not_ + verify its signature. AppAuth only supports the OpenID Code flow, meaning ID Tokens + received by AppAuth are sent from the token endpoint on a TLS protected channel, + offering some assurances as to the origin of the token. You may wish to additionally + verify the ID Token signature using a JWT signature verification library of your + choosing. + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + @see https://tools.ietf.org/html/rfc7519 + @see https://jwt.io/ + */ +@interface OIDIDToken : NSObject + +/*! @internal + @brief Unavailable. Please use @c initWithAuthorizationResponse:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Parses the given ID Token string. + @param idToken The ID Token spring. + */ +- (nullable instancetype)initWithIDTokenString:(NSString *)idToken; + +/*! @brief The header JWT values. + */ +@property(nonatomic, readonly) NSDictionary *header; + +/*! @brief All ID Token claims. + */ +@property(nonatomic, readonly) NSDictionary *claims; + +/*! @brief Issuer Identifier for the Issuer of the response. + @remarks iss + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly) NSURL *issuer; + +/*! @brief Subject Identifier. + @remarks sub + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly) NSString *subject; + +/*! @brief Audience(s) that this ID Token is intended for. + @remarks aud + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly) NSArray *audience; + +/*! @brief Expiration time on or after which the ID Token MUST NOT be accepted for processing. + @remarks exp + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly) NSDate *expiresAt; + +/*! @brief Time at which the JWT was issued. + @remarks iat + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly) NSDate *issuedAt; + +/*! @brief String value used to associate a Client session with an ID Token, and to mitigate replay + attacks. + @remarks nonce + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + */ +@property(nonatomic, readonly, nullable) NSString *nonce; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.m new file mode 100644 index 00000000..57a7324e --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDIDToken.m @@ -0,0 +1,149 @@ +/*! @file OIDIDToken.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDIDToken.h" + +/*! Field keys associated with an ID Token. */ +static NSString *const kIssKey = @"iss"; +static NSString *const kSubKey = @"sub"; +static NSString *const kAudKey = @"aud"; +static NSString *const kExpKey = @"exp"; +static NSString *const kIatKey = @"iat"; +static NSString *const kNonceKey = @"nonce"; + +#import "OIDFieldMapping.h" + +@implementation OIDIDToken + +- (instancetype)initWithIDTokenString:(NSString *)idToken { + self = [super init]; + NSArray *sections = [idToken componentsSeparatedByString:@"."]; + + // The header and claims sections are required. + if (sections.count <= 1) { + return nil; + } + + _header = [[self class] parseJWTSection:sections[0]]; + _claims = [[self class] parseJWTSection:sections[1]]; + if (!_header || !_claims) { + return nil; + } + + [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap] + parameters:_claims + instance:self]; + + // Required fields. + if (!_issuer || !_audience || !_subject || !_expiresAt || !_issuedAt) { + return nil; + } + + return self; +} + +/*! @brief Returns a mapping of incoming parameters to instance variables. + @return A mapping of incoming parameters to instance variables. + */ ++ (NSDictionary *)fieldMap { + static NSMutableDictionary *fieldMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fieldMap = [NSMutableDictionary dictionary]; + + fieldMap[kIssKey] = + [[OIDFieldMapping alloc] initWithName:@"_issuer" + type:[NSURL class] + conversion:[OIDFieldMapping URLConversion]]; + fieldMap[kSubKey] = + [[OIDFieldMapping alloc] initWithName:@"_subject" type:[NSString class]]; + fieldMap[kAudKey] = + [[OIDFieldMapping alloc] initWithName:@"_audience" + type:[NSArray class] + conversion:^id _Nullable(NSObject *_Nullable value) { + if ([value isKindOfClass:[NSArray class]]) { + return value; + } + if ([value isKindOfClass:[NSString class]]) { + return @[value]; + } + return nil; + }]; + fieldMap[kExpKey] = + [[OIDFieldMapping alloc] initWithName:@"_expiresAt" + type:[NSDate class] + conversion:^id _Nullable(NSObject *_Nullable value) { + if (![value isKindOfClass:[NSNumber class]]) { + return value; + } + NSNumber *valueAsNumber = (NSNumber *)value; + return [NSDate dateWithTimeIntervalSince1970:valueAsNumber.longLongValue]; + }]; + fieldMap[kIatKey] = + [[OIDFieldMapping alloc] initWithName:@"_issuedAt" + type:[NSDate class] + conversion:^id _Nullable(NSObject *_Nullable value) { + if (![value isKindOfClass:[NSNumber class]]) { + return value; + } + NSNumber *valueAsNumber = (NSNumber *)value; + return [NSDate dateWithTimeIntervalSince1970:valueAsNumber.longLongValue]; + }]; + fieldMap[kNonceKey] = + [[OIDFieldMapping alloc] initWithName:@"_nonce" type:[NSString class]]; + }); + return fieldMap; +} + ++ (NSDictionary *)parseJWTSection:(NSString *)sectionString { + NSData *decodedData = [[self class] base64urlNoPaddingDecode:sectionString]; + + // Parses JSON. + NSError *error; + id object = [NSJSONSerialization JSONObjectWithData:decodedData options:0 error:&error]; + if (error) { + NSLog(@"Error %@ parsing token payload %@", error, sectionString); + } + if ([object isKindOfClass:[NSDictionary class]]) { + return (NSDictionary *)object; + } + + return nil; +} + ++ (NSData *)base64urlNoPaddingDecode:(NSString *)base64urlNoPaddingString { + NSMutableString *body = [base64urlNoPaddingString mutableCopy]; + + // Converts base64url to base64. + NSRange range = NSMakeRange(0, base64urlNoPaddingString.length); + [body replaceOccurrencesOfString:@"-" withString:@"+" options:NSLiteralSearch range:range]; + [body replaceOccurrencesOfString:@"_" withString:@"/" options:NSLiteralSearch range:range]; + + // Converts base64 no padding to base64 with padding + while (body.length % 4 != 0) { + [body appendString:@"="]; + } + + // Decodes base64 string. + NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:body options:0]; + return decodedData; +} + +@end + + diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.h new file mode 100644 index 00000000..e509c60a --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.h @@ -0,0 +1,141 @@ +/*! @file OIDRegistrationRequest.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthorizationResponse; +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents a registration request. + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest + */ +@interface OIDRegistrationRequest : NSObject + +/*! @brief The service's configuration. + @remarks This configuration specifies how to connect to a particular OAuth provider. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @brief The initial access token to access the Client Registration Endpoint + (if required by the OpenID Provider). + @remarks OAuth 2.0 Access Token optionally issued by an Authorization Server granting + access to its Client Registration Endpoint. This token (if required) is + provisioned out of band. + @see Section 3 of OpenID Connect Dynamic Client Registration 1.0 + https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration + */ +@property(nonatomic, readonly) NSString *initialAccessToken; + +/*! @brief The application type to register, will always be 'native'. + @remarks application_type + @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata + */ +@property(nonatomic, readonly) NSString *applicationType; + +/*! @brief The client's redirect URI's. + @remarks redirect_uris + @see https://tools.ietf.org/html/rfc6749#section-3.1.2 + */ +@property(nonatomic, readonly) NSArray *redirectURIs; + +/*! @brief The response types to register for usage by this client. + @remarks response_types + @see http://openid.net/specs/openid-connect-core-1_0.html#Authentication + */ +@property(nonatomic, readonly, nullable) NSArray *responseTypes; + +/*! @brief The grant types to register for usage by this client. + @remarks grant_types + @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata + */ +@property(nonatomic, readonly, nullable) NSArray *grantTypes; + +/*! @brief The subject type to to request. + @remarks subject_type + @see http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes + */ +@property(nonatomic, readonly, nullable) NSString *subjectType; + +/*! @brief The client authentication method to use at the token endpoint. + @remarks token_endpoint_auth_method + @see http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication + */ +@property(nonatomic, readonly, nullable) NSString *tokenEndpointAuthenticationMethod; + +/*! @brief The client's additional token request parameters. + */ +@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters; + +/*! @internal + @brief Unavailable. Please use initWithConfiguration + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Create a Client Registration Request to an OpenID Provider that supports open Dynamic + Registration. + @param configuration The service's configuration. + @param redirectURIs The redirect URIs to register for the client. + @param responseTypes The response types to register for the client. + @param grantTypes The grant types to register for the client. + @param subjectType The subject type to register for the client. + @param tokenEndpointAuthMethod The token endpoint authentication method to register for the + client. + @param additionalParameters The client's additional registration request parameters. + */ +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + redirectURIs:(NSArray *)redirectURIs + responseTypes:(nullable NSArray *)responseTypes + grantTypes:(nullable NSArray *)grantTypes + subjectType:(nullable NSString *)subjectType + tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Designated initializer. + @param configuration The service's configuration. + @param redirectURIs The redirect URIs to register for the client. + @param responseTypes The response types to register for the client. + @param grantTypes The grant types to register for the client. + @param subjectType The subject type to register for the client. + @param tokenEndpointAuthMethod The token endpoint authentication method to register for the + client. + @param initialAccessToken The initial access token to access the Client Registration Endpoint + (if required by the OpenID Provider). + @param additionalParameters The client's additional registration request parameters. + @see https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration + */ +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + redirectURIs:(NSArray *)redirectURIs + responseTypes:(nullable NSArray *)responseTypes + grantTypes:(nullable NSArray *)grantTypes + subjectType:(nullable NSString *)subjectType + tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod + initialAccessToken:(nullable NSString *)initialAccessToken + additionalParameters:(nullable NSDictionary *)additionalParameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Constructs an @c NSURLRequest representing the registration request. + @return An @c NSURLRequest representing the registration request. + */ +- (NSURLRequest *)URLRequest; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.m new file mode 100644 index 00000000..9efd18fd --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationRequest.m @@ -0,0 +1,248 @@ +/*! @file OIDRegistrationRequest.m + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDRegistrationRequest.h" + +#import "OIDClientMetadataParameters.h" +#import "OIDDefines.h" +#import "OIDServiceConfiguration.h" + +/*! @brief The key for the @c configuration property for @c NSSecureCoding + */ +static NSString *const kConfigurationKey = @"configuration"; + +/*! @brief The key for the @c initialAccessToken property for @c NSSecureCoding + */ +static NSString *const kInitialAccessToken = @"initial_access_token"; + +/*! @brief Key used to encode the @c redirectURIs property for @c NSSecureCoding + */ +static NSString *const kRedirectURIsKey = @"redirect_uris"; + +/*! @brief The key for the @c responseTypes property for @c NSSecureCoding. + */ +static NSString *const kResponseTypesKey = @"response_types"; + +/*! @brief Key used to encode the @c grantType property for @c NSSecureCoding + */ +static NSString *const kGrantTypesKey = @"grant_types"; + +/*! @brief Key used to encode the @c subjectType property for @c NSSecureCoding + */ +static NSString *const kSubjectTypeKey = @"subject_type"; + +/*! @brief Key used to encode the @c additionalParameters property for + @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +@implementation OIDRegistrationRequest + +#pragma mark - Initializers + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER( + @selector(initWithConfiguration: + redirectURIs: + responseTypes: + grantTypes: + subjectType: + tokenEndpointAuthMethod: + additionalParameters:) + ) + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + redirectURIs:(NSArray *)redirectURIs + responseTypes:(nullable NSArray *)responseTypes + grantTypes:(nullable NSArray *)grantTypes + subjectType:(nullable NSString *)subjectType + tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod + additionalParameters:(nullable NSDictionary *)additionalParameters { + return [self initWithConfiguration:configuration + redirectURIs:redirectURIs + responseTypes:responseTypes + grantTypes:grantTypes + subjectType:subjectType + tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod + initialAccessToken:nil + additionalParameters:additionalParameters]; +} + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + redirectURIs:(NSArray *)redirectURIs + responseTypes:(nullable NSArray *)responseTypes + grantTypes:(nullable NSArray *)grantTypes + subjectType:(nullable NSString *)subjectType + tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod + initialAccessToken:(nullable NSString *)initialAccessToken + additionalParameters:(nullable NSDictionary *)additionalParameters { + self = [super init]; + if (self) { + _configuration = [configuration copy]; + _initialAccessToken = [initialAccessToken copy]; + _redirectURIs = [redirectURIs copy]; + _responseTypes = [responseTypes copy]; + _grantTypes = [grantTypes copy]; + _subjectType = [subjectType copy]; + _tokenEndpointAuthenticationMethod = [tokenEndpointAuthenticationMethod copy]; + _additionalParameters = + [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES]; + + _applicationType = OIDApplicationTypeNative; + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDServiceConfiguration *configuration = + [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] + forKey:kConfigurationKey]; + NSString *initialAccessToken = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kInitialAccessToken]; + NSArray *redirectURIs = [aDecoder decodeObjectOfClass:[NSArray class] + forKey:kRedirectURIsKey]; + NSArray *responseTypes = [aDecoder decodeObjectOfClass:[NSArray class] + forKey:kResponseTypesKey]; + NSArray *grantTypes = [aDecoder decodeObjectOfClass:[NSArray class] + forKey:kGrantTypesKey]; + NSString *subjectType = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kSubjectTypeKey]; + NSString *tokenEndpointAuthenticationMethod = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:OIDTokenEndpointAuthenticationMethodParam]; + NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ [NSDictionary class], + [NSString class] ]]; + NSDictionary *additionalParameters = + [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses + forKey:kAdditionalParametersKey]; + self = [self initWithConfiguration:configuration + redirectURIs:redirectURIs + responseTypes:responseTypes + grantTypes:grantTypes + subjectType:subjectType + tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod + initialAccessToken:initialAccessToken + additionalParameters:additionalParameters]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_configuration forKey:kConfigurationKey]; + [aCoder encodeObject:_initialAccessToken forKey:kInitialAccessToken]; + [aCoder encodeObject:_redirectURIs forKey:kRedirectURIsKey]; + [aCoder encodeObject:_responseTypes forKey:kResponseTypesKey]; + [aCoder encodeObject:_grantTypes forKey:kGrantTypesKey]; + [aCoder encodeObject:_subjectType forKey:kSubjectTypeKey]; + [aCoder encodeObject:_tokenEndpointAuthenticationMethod + forKey:OIDTokenEndpointAuthenticationMethodParam]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + NSURLRequest *request = [self URLRequest]; + NSString *requestBody = [[NSString alloc] initWithData:request.HTTPBody + encoding:NSUTF8StringEncoding]; + return [NSString stringWithFormat:@"<%@: %p, request: >", + NSStringFromClass([self class]), + (void *)self, + request.URL, + requestBody]; +} + +- (NSURLRequest *)URLRequest { + static NSString *const kHTTPPost = @"POST"; + static NSString *const kBearer = @"Bearer"; + static NSString *const kHTTPContentTypeHeaderKey = @"Content-Type"; + static NSString *const kHTTPContentTypeHeaderValue = @"application/json"; + static NSString *const kHTTPAuthorizationHeaderKey = @"Authorization"; + + NSData *postBody = [self JSONString]; + if (!postBody) { + return nil; + } + + NSURL *registrationRequestURL = _configuration.registrationEndpoint; + NSMutableURLRequest *URLRequest = + [[NSURLRequest requestWithURL:registrationRequestURL] mutableCopy]; + URLRequest.HTTPMethod = kHTTPPost; + [URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey]; + if (_initialAccessToken) { + NSString *value = [NSString stringWithFormat:@"%@ %@", kBearer, _initialAccessToken]; + [URLRequest setValue:value forHTTPHeaderField:kHTTPAuthorizationHeaderKey]; + } + URLRequest.HTTPBody = postBody; + return URLRequest; +} + +- (NSData *)JSONString { + // Dictionary with several kay/value pairs and the above array of arrays + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + NSMutableArray *redirectURIStrings = + [NSMutableArray arrayWithCapacity:[_redirectURIs count]]; + for (id obj in _redirectURIs) { + [redirectURIStrings addObject:[obj absoluteString]]; + } + dict[OIDRedirectURIsParam] = redirectURIStrings; + dict[OIDApplicationTypeParam] = _applicationType; + + if (_additionalParameters) { + // Add any additional parameters first to allow them + // to be overwritten by instance values + [dict addEntriesFromDictionary:_additionalParameters]; + } + if (_responseTypes) { + dict[OIDResponseTypesParam] = _responseTypes; + } + if (_grantTypes) { + dict[OIDGrantTypesParam] = _grantTypes; + } + if (_subjectType) { + dict[OIDSubjectTypeParam] = _subjectType; + } + if (_tokenEndpointAuthenticationMethod) { + dict[OIDTokenEndpointAuthenticationMethodParam] = _tokenEndpointAuthenticationMethod; + } + + NSError *error; + NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&error]; + if (json == nil || error != nil) { + return nil; + } + + return json; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.h new file mode 100644 index 00000000..df623906 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.h @@ -0,0 +1,126 @@ +/*! @file OIDRegistrationResponse.h + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#import + +@class OIDRegistrationRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Parameter name for the client id. + */ +extern NSString *const OIDClientIDParam; + +/*! @brief Parameter name for the client id issuance timestamp. + */ +extern NSString *const OIDClientIDIssuedAtParam; + +/*! @brief Parameter name for the client secret. + */ +extern NSString *const OIDClientSecretParam; + +/*! @brief Parameter name for the client secret expiration time. + */ +extern NSString *const OIDClientSecretExpirestAtParam; + +/*! @brief Parameter name for the registration access token. + */ +extern NSString *const OIDRegistrationAccessTokenParam; + +/*! @brief Parameter name for the client configuration URI. + */ +extern NSString *const OIDRegistrationClientURIParam; + +/*! @brief Represents a registration response. + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@interface OIDRegistrationResponse : NSObject + +/*! @brief The request which was serviced. + */ +@property(nonatomic, readonly) OIDRegistrationRequest *request; + +/*! @brief The registered client identifier. + @remarks client_id + @see https://tools.ietf.org/html/rfc6749#section-4 + @see https://tools.ietf.org/html/rfc6749#section-4.1.1 + */ +@property(nonatomic, readonly) NSString *clientID; + +/*! @brief Timestamp of when the client identifier was issued, if provided. + @remarks client_id_issued_at + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@property(nonatomic, readonly, nullable) NSDate *clientIDIssuedAt; + +/*! @brief TThe client secret, which is part of the client credentials, if provided. + @remarks client_secret + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@property(nonatomic, readonly, nullable) NSString *clientSecret; + +/*! @brief Timestamp of when the client credentials expires, if provided. + @remarks client_secret_expires_at + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@property(nonatomic, readonly, nullable) NSDate *clientSecretExpiresAt; + +/*! @brief Client registration access token that can be used for subsequent operations upon the + client registration. + @remarks registration_access_token + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@property(nonatomic, readonly, nullable) NSString *registrationAccessToken; + +/*! @brief Location of the client configuration endpoint, if provided. + @remarks registration_client_uri + @see https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse + */ +@property(nonatomic, readonly, nullable) NSURL *registrationClientURI; + +/*! @brief Client authentication method to use at the token endpoint, if provided. + @remarks token_endpoint_auth_method + @see http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication + */ +@property(nonatomic, readonly, nullable) NSString *tokenEndpointAuthenticationMethod; + +/*! @brief Additional parameters returned from the token server. + */ +@property(nonatomic, readonly, nullable) NSDictionary *> + *additionalParameters; + +/*! @internal + @brief Unavailable. Please use initWithRequest + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Designated initializer. + @param request The serviced request. + @param parameters The decoded parameters returned from the Authorization Server. + @remarks Known parameters are extracted from the @c parameters parameter and the normative + properties are populated. Non-normative parameters are placed in the + @c #additionalParameters dictionary. + */ +- (instancetype)initWithRequest:(OIDRegistrationRequest *)request + parameters:(NSDictionary *> *)parameters + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.m new file mode 100644 index 00000000..ec0411b7 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDRegistrationResponse.m @@ -0,0 +1,164 @@ +/*! @file OIDRegistrationResponse.m + @brief AppAuth iOS SDK + @copyright + Copyright 2016 The AppAuth for iOS Authors. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDRegistrationResponse.h" + +#import "OIDClientMetadataParameters.h" +#import "OIDDefines.h" +#import "OIDFieldMapping.h" +#import "OIDRegistrationRequest.h" +#import "OIDTokenUtilities.h" + +NSString *const OIDClientIDParam = @"client_id"; +NSString *const OIDClientIDIssuedAtParam = @"client_id_issued_at"; +NSString *const OIDClientSecretParam = @"client_secret"; +NSString *const OIDClientSecretExpirestAtParam = @"client_secret_expires_at"; +NSString *const OIDRegistrationAccessTokenParam = @"registration_access_token"; +NSString *const OIDRegistrationClientURIParam = @"registration_client_uri"; + +/*! @brief Key used to encode the @c request property for @c NSSecureCoding + */ +static NSString *const kRequestKey = @"request"; + +/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +@implementation OIDRegistrationResponse + +/*! @brief Returns a mapping of incoming parameters to instance variables. + @return A mapping of incoming parameters to instance variables. + */ ++ (NSDictionary *)fieldMap { + static NSMutableDictionary *fieldMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fieldMap = [NSMutableDictionary dictionary]; + fieldMap[OIDClientIDParam] = [[OIDFieldMapping alloc] initWithName:@"_clientID" + type:[NSString class]]; + fieldMap[OIDClientIDIssuedAtParam] = + [[OIDFieldMapping alloc] initWithName:@"_clientIDIssuedAt" + type:[NSDate class] + conversion:[OIDFieldMapping dateEpochConversion]]; + fieldMap[OIDClientSecretParam] = + [[OIDFieldMapping alloc] initWithName:@"_clientSecret" + type:[NSString class]]; + fieldMap[OIDClientSecretExpirestAtParam] = + [[OIDFieldMapping alloc] initWithName:@"_clientSecretExpiresAt" + type:[NSDate class] + conversion:[OIDFieldMapping dateEpochConversion]]; + fieldMap[OIDRegistrationAccessTokenParam] = + [[OIDFieldMapping alloc] initWithName:@"_registrationAccessToken" + type:[NSString class]]; + fieldMap[OIDRegistrationClientURIParam] = + [[OIDFieldMapping alloc] initWithName:@"_registrationClientURI" + type:[NSURL class] + conversion:[OIDFieldMapping URLConversion]]; + fieldMap[OIDTokenEndpointAuthenticationMethodParam] = + [[OIDFieldMapping alloc] initWithName:@"_tokenEndpointAuthenticationMethod" + type:[NSString class]]; + }); + return fieldMap; +} + + +#pragma mark - Initializers + +- (nonnull instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:)) + +- (instancetype)initWithRequest:(OIDRegistrationRequest *)request + parameters:(NSDictionary *> *)parameters { + self = [super init]; + if (self) { + _request = [request copy]; + NSDictionary *> *additionalParameters = + [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap] + parameters:parameters + instance:self]; + _additionalParameters = additionalParameters; + + if ((_clientSecret && !_clientSecretExpiresAt) + || (!!_registrationClientURI != !!_registrationAccessToken)) { + // If client_secret is issued, client_secret_expires_at is REQUIRED, + // and the response MUST contain "[...] both a Client Configuration Endpoint + // and a Registration Access Token or neither of them" + return nil; + } + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDRegistrationRequest *request = [aDecoder decodeObjectOfClass:[OIDRegistrationRequest class] + forKey:kRequestKey]; + self = [self initWithRequest:request + parameters:@{}]; + if (self) { + [OIDFieldMapping decodeWithCoder:aDecoder + map:[[self class] fieldMap] + instance:self]; + _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes] + forKey:kAdditionalParametersKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self]; + [aCoder encodeObject:_request forKey:kRequestKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, clientID: \"%@\", clientIDIssuedAt: %@, " + "clientSecret: %@, clientSecretExpiresAt: \"%@\", " + "registrationAccessToken: \"%@\", " + "registrationClientURI: \"%@\", " + "additionalParameters: %@, request: %@>", + NSStringFromClass([self class]), + (void *)self, + _clientID, + _clientIDIssuedAt, + [OIDTokenUtilities redact:_clientSecret], + _clientSecretExpiresAt, + [OIDTokenUtilities redact:_registrationAccessToken], + _registrationClientURI, + _additionalParameters, + _request]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.h new file mode 100644 index 00000000..405ef938 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.h @@ -0,0 +1,31 @@ +/*! @file OIDResponseTypes.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +/*! @brief A constant for the standard OAuth2 Response Type of 'code'. + */ +extern NSString *const OIDResponseTypeCode; + +/*! @brief A constant for the standard OAuth2 Response Type of 'token'. + */ +extern NSString *const OIDResponseTypeToken; + +/*! @brief A constant for the standard OAuth2 Response Type of 'id_token'. + */ +extern NSString *const OIDResponseTypeIDToken; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.m new file mode 100644 index 00000000..78eaf187 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDResponseTypes.m @@ -0,0 +1,25 @@ +/*! @file OIDResponseTypes.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDResponseTypes.h" + +NSString *const OIDResponseTypeCode = @"code"; + +NSString *const OIDResponseTypeToken = @"token"; + +NSString *const OIDResponseTypeIDToken = @"id_token"; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.h new file mode 100644 index 00000000..c0a5190c --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.h @@ -0,0 +1,48 @@ +/*! @file OIDScopeUtilities.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Provides convenience methods for dealing with scope strings. + */ +@interface OIDScopeUtilities : NSObject + +/*! @internal + @brief Unavailable. This class should not be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Converts an array of scope strings to a single scope string per the OAuth 2 spec. + @param scopes An array of scope strings. + @return A space-delimited string of scopes. + @see https://tools.ietf.org/html/rfc6749#section-3.3 + */ ++ (NSString *)scopesWithArray:(NSArray *)scopes; + +/*! @brief Converts an OAuth 2 spec-compliant scope string to an array of scopes. + @param scopes An OAuth 2 spec-compliant scope string. + @return An array of scope strings. + @see https://tools.ietf.org/html/rfc6749#section-3.3 + */ ++ (NSArray *)scopesArrayWithString:(NSString *)scopes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.m new file mode 100644 index 00000000..a0bcb8c8 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopeUtilities.m @@ -0,0 +1,58 @@ +/*! @file OIDScopeUtilities.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDScopeUtilities.h" + +@implementation OIDScopeUtilities + +/*! @brief A character set with the characters NOT allowed in a scope name. + @see https://tools.ietf.org/html/rfc6749#section-3.3 + */ ++ (NSCharacterSet *)disallowedScopeCharacters { + static NSCharacterSet *disallowedCharacters; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableCharacterSet *allowedCharacters; + allowedCharacters = + [NSMutableCharacterSet characterSetWithRange:NSMakeRange(0x23, 0x5B - 0x23 + 1)]; + [allowedCharacters addCharactersInRange:NSMakeRange(0x5D, 0x7E - 0x5D + 1)]; + [allowedCharacters addCharactersInString:@"\x21"]; + disallowedCharacters = [allowedCharacters invertedSet]; + }); + return disallowedCharacters; +} + ++ (NSString *)scopesWithArray:(NSArray *)scopes { +#if !defined(NS_BLOCK_ASSERTIONS) + NSCharacterSet *disallowedCharacters = [self disallowedScopeCharacters]; + for (NSString *scope in scopes) { + NSAssert(scope.length, @"Found illegal empty scope string."); + NSAssert([scope rangeOfCharacterFromSet:disallowedCharacters].location == NSNotFound, + @"Found illegal character in scope string."); + } +#endif // !defined(NS_BLOCK_ASSERTIONS) + + NSString *scopeString = [scopes componentsJoinedByString:@" "]; + return scopeString; +} + ++ (NSArray *)scopesArrayWithString:(NSString *)scopes { + return [scopes componentsSeparatedByString:@" "]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.h new file mode 100644 index 00000000..da8bb189 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.h @@ -0,0 +1,46 @@ +/*! @file OIDScopes.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +/*! @brief Scope that indicates this request is an OpenID Connect request. + @see http://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation + */ +extern NSString *const OIDScopeOpenID; + +/*! @brief This scope value requests access to the End-User's default profile Claims, which are: + name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture, + website, gender, birthdate, zoneinfo, locale, and updated_at. + @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims + */ +extern NSString *const OIDScopeProfile; + +/*! @brief This scope value requests access to the email and email_verified Claims. + @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims + */ +extern NSString *const OIDScopeEmail; + +/*! @brief This scope value requests access to the address Claim. + @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims + */ +extern NSString *const OIDScopeAddress; + +/*! @brief This scope value requests access to the phone_number and phone_number_verified Claims. + @see http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims + */ +extern NSString *const OIDScopePhone; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.m new file mode 100644 index 00000000..62dd707e --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDScopes.m @@ -0,0 +1,29 @@ +/*! @file OIDScopes.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDScopes.h" + +NSString *const OIDScopeOpenID = @"openid"; + +NSString *const OIDScopeProfile = @"profile"; + +NSString *const OIDScopeEmail = @"email"; + +NSString *const OIDScopeAddress = @"address"; + +NSString *const OIDScopePhone = @"phone"; diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.h new file mode 100644 index 00000000..a072a478 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.h @@ -0,0 +1,118 @@ +/*! @file OIDServiceConfiguration.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDServiceConfiguration; +@class OIDServiceDiscovery; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief The type of block called when a @c OIDServiceConfiguration has been created + by loading a @c OIDServiceDiscovery from an @c NSURL. + */ +typedef void (^OIDServiceConfigurationCreated) + (OIDServiceConfiguration *_Nullable serviceConfiguration, + NSError *_Nullable error); + +/*! @brief Represents the information needed to construct a @c OIDAuthorizationService. + */ +@interface OIDServiceConfiguration : NSObject + +/*! @brief The authorization endpoint URI. + */ +@property(nonatomic, readonly) NSURL *authorizationEndpoint; + +/*! @brief The token exchange and refresh endpoint URI. + */ +@property(nonatomic, readonly) NSURL *tokenEndpoint; + +/*! @brief The OpenID Connect issuer. + */ +@property(nonatomic, readonly, nullable) NSURL *issuer; + +/*! @brief The dynamic client registration endpoint URI. + */ +@property(nonatomic, readonly, nullable) NSURL *registrationEndpoint; + +/*! @brief The end session logout endpoint URI. + */ +@property(nonatomic, readonly, nullable) NSURL *endSessionEndpoint; + +/*! @brief The discovery document. + */ +@property(nonatomic, readonly, nullable) OIDServiceDiscovery *discoveryDocument; + +/*! @internal + @brief Unavailable. Please use @c initWithAuthorizationEndpoint:tokenEndpoint: or + @c initWithDiscoveryDocument:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @param authorizationEndpoint The authorization endpoint URI. + @param tokenEndpoint The token exchange and refresh endpoint URI. + */ +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint; + +/*! @param authorizationEndpoint The authorization endpoint URI. + @param tokenEndpoint The token exchange and refresh endpoint URI. + @param registrationEndpoint The dynamic client registration endpoint URI. + */ +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + registrationEndpoint:(nullable NSURL *)registrationEndpoint; + +/*! @param authorizationEndpoint The authorization endpoint URI. + @param tokenEndpoint The token exchange and refresh endpoint URI. + @param issuer The OpenID Connect issuer. + */ +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer; + +/*! @param authorizationEndpoint The authorization endpoint URI. + @param tokenEndpoint The token exchange and refresh endpoint URI. + @param issuer The OpenID Connect issuer. + @param registrationEndpoint The dynamic client registration endpoint URI. + */ +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint; + +/*! @param authorizationEndpoint The authorization endpoint URI. + @param tokenEndpoint The token exchange and refresh endpoint URI. + @param issuer The OpenID Connect issuer. + @param registrationEndpoint The dynamic client registration endpoint URI. + @param endSessionEndpoint The end session endpoint (logout) URI. + */ +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint + endSessionEndpoint:(nullable NSURL *)endSessionEndpoint; + +/*! @param discoveryDocument The discovery document from which to extract the required OAuth + configuration. + */ +- (instancetype)initWithDiscoveryDocument:(OIDServiceDiscovery *)discoveryDocument; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.m new file mode 100644 index 00000000..ca48a8c3 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceConfiguration.m @@ -0,0 +1,223 @@ +/*! @file OIDServiceConfiguration.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDServiceConfiguration.h" + +#import "OIDDefines.h" +#import "OIDErrorUtilities.h" +#import "OIDServiceDiscovery.h" + +/*! @brief The key for the @c authorizationEndpoint property. + */ +static NSString *const kAuthorizationEndpointKey = @"authorizationEndpoint"; + +/*! @brief The key for the @c tokenEndpoint property. + */ +static NSString *const kTokenEndpointKey = @"tokenEndpoint"; + +/*! @brief The key for the @c issuer property. + */ +static NSString *const kIssuerKey = @"issuer"; + +/*! @brief The key for the @c registrationEndpoint property. + */ +static NSString *const kRegistrationEndpointKey = @"registrationEndpoint"; + +/*! @brief The key for the @c endSessionEndpoint property. + */ +static NSString *const kEndSessionEndpointKey = @"endSessionEndpoint"; + +/*! @brief The key for the @c discoveryDocument property. + */ +static NSString *const kDiscoveryDocumentKey = @"discoveryDocument"; + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDServiceConfiguration () + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint + endSessionEndpoint:(nullable NSURL *)endSessionEndpoint + discoveryDocument:(nullable OIDServiceDiscovery *)discoveryDocument + NS_DESIGNATED_INITIALIZER; + +@end + +@implementation OIDServiceConfiguration + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector( + initWithAuthorizationEndpoint: + tokenEndpoint:) + ) + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint + endSessionEndpoint:(nullable OIDServiceDiscovery *)endSessionEndpoint + discoveryDocument:(nullable OIDServiceDiscovery *)discoveryDocument { + + self = [super init]; + if (self) { + _authorizationEndpoint = [authorizationEndpoint copy]; + _tokenEndpoint = [tokenEndpoint copy]; + _issuer = [issuer copy]; + _registrationEndpoint = [registrationEndpoint copy]; + _endSessionEndpoint = [endSessionEndpoint copy]; + _discoveryDocument = [discoveryDocument copy]; + } + return self; +} + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint { + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:nil + registrationEndpoint:nil + endSessionEndpoint:nil + discoveryDocument:nil]; +} + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + registrationEndpoint:(nullable NSURL *)registrationEndpoint { + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:nil + registrationEndpoint:registrationEndpoint + endSessionEndpoint:nil + discoveryDocument:nil]; +} + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer { + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:issuer + registrationEndpoint:nil + endSessionEndpoint:nil + discoveryDocument:nil]; +} + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint { + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:issuer + registrationEndpoint:registrationEndpoint + endSessionEndpoint:nil + discoveryDocument:nil]; +} + +- (instancetype)initWithAuthorizationEndpoint:(NSURL *)authorizationEndpoint + tokenEndpoint:(NSURL *)tokenEndpoint + issuer:(nullable NSURL *)issuer + registrationEndpoint:(nullable NSURL *)registrationEndpoint + endSessionEndpoint:(nullable NSURL *)endSessionEndpoint { + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:issuer + registrationEndpoint:registrationEndpoint + endSessionEndpoint:endSessionEndpoint + discoveryDocument:nil]; +} + +- (instancetype)initWithDiscoveryDocument:(OIDServiceDiscovery *) discoveryDocument { + return [self initWithAuthorizationEndpoint:discoveryDocument.authorizationEndpoint + tokenEndpoint:discoveryDocument.tokenEndpoint + issuer:discoveryDocument.issuer + registrationEndpoint:discoveryDocument.registrationEndpoint + endSessionEndpoint:discoveryDocument.endSessionEndpoint + discoveryDocument:discoveryDocument]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSURL *authorizationEndpoint = [aDecoder decodeObjectOfClass:[NSURL class] + forKey:kAuthorizationEndpointKey]; + NSURL *tokenEndpoint = [aDecoder decodeObjectOfClass:[NSURL class] + forKey:kTokenEndpointKey]; + NSURL *issuer = [aDecoder decodeObjectOfClass:[NSURL class] + forKey:kIssuerKey]; + NSURL *registrationEndpoint = [aDecoder decodeObjectOfClass:[NSURL class] + forKey:kRegistrationEndpointKey]; + NSURL *endSessionEndpoint = [aDecoder decodeObjectOfClass:[NSURL class] + forKey:kEndSessionEndpointKey]; + // We don't accept nil authorizationEndpoints or tokenEndpoints. + if (!authorizationEndpoint || !tokenEndpoint) { + return nil; + } + + OIDServiceDiscovery *discoveryDocument = [aDecoder decodeObjectOfClass:[OIDServiceDiscovery class] + forKey:kDiscoveryDocumentKey]; + + return [self initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint + issuer:issuer + registrationEndpoint:registrationEndpoint + endSessionEndpoint:endSessionEndpoint + discoveryDocument:discoveryDocument]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_authorizationEndpoint forKey:kAuthorizationEndpointKey]; + [aCoder encodeObject:_tokenEndpoint forKey:kTokenEndpointKey]; + [aCoder encodeObject:_issuer forKey:kIssuerKey]; + [aCoder encodeObject:_registrationEndpoint forKey:kRegistrationEndpointKey]; + [aCoder encodeObject:_discoveryDocument forKey:kDiscoveryDocumentKey]; + [aCoder encodeObject:_endSessionEndpoint forKey:kEndSessionEndpointKey]; +} + +#pragma mark - description + +- (NSString *)description { + return [NSString stringWithFormat: + @"OIDServiceConfiguration authorizationEndpoint: %@, tokenEndpoint: %@, " + "registrationEndpoint: %@, endSessionEndpoint: %@, discoveryDocument: [%@]", + _authorizationEndpoint, + _tokenEndpoint, + _registrationEndpoint, + _endSessionEndpoint, + _discoveryDocument]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.h new file mode 100644 index 00000000..57770083 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.h @@ -0,0 +1,358 @@ +/*! @file OIDServiceDiscovery.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents an OpenID Connect 1.0 Discovery Document + @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata + */ +@interface OIDServiceDiscovery : NSObject + +/*! @brief The decoded OpenID Connect 1.0 Discovery Document as a dictionary. + */ +@property(nonatomic, readonly) NSDictionary *discoveryDictionary; + +/*! @brief REQUIRED. URL using the @c https scheme with no query or fragment component that the OP + asserts as its Issuer Identifier. If Issuer discovery is supported, this value MUST be + identical to the issuer value returned by WebFinger. This also MUST be identical to the + @c iss Claim value in ID Tokens issued from this Issuer. + @remarks issuer + @seealso https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery + */ +@property(nonatomic, readonly) NSURL *issuer; + +/*! @brief REQUIRED. URL of the OP's OAuth 2.0 Authorization Endpoint. + @remarks authorization_endpoint + @seealso http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint + */ +@property(nonatomic, readonly) NSURL *authorizationEndpoint; + +/*! @brief URL of the OP's OAuth 2.0 Token Endpoint. This is REQUIRED unless only the Implicit Flow + is used. + @remarks token_endpoint + @seealso http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint + */ +@property(nonatomic, readonly) NSURL *tokenEndpoint; + +/*! @brief RECOMMENDED. URL of the OP's UserInfo Endpoint. This URL MUST use the https scheme and + MAY contain port, path, and query parameter components. + @remarks userinfo_endpoint + @seealso http://openid.net/specs/openid-connect-core-1_0.html#UserInfo + */ +@property(nonatomic, readonly, nullable) NSURL *userinfoEndpoint; + +/*! @brief REQUIRED. URL of the OP's JSON Web Key Set document. This contains the signing key(s) the + RP uses to validate signatures from the OP. The JWK Set MAY also contain the Server's + encryption key(s), which are used by RPs to encrypt requests to the Server. When both + signing and encryption keys are made available, a use (Key Use) parameter value is REQUIRED + for all keys in the referenced JWK Set to indicate each key's intended usage. Although some + algorithms allow the same key to be used for both signatures and encryption, doing so is NOT + RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be used to provide X.509 + representations of keys provided. When used, the bare key values MUST still be present and + MUST match those in the certificate. + @remarks jwks_uri + @seealso http://tools.ietf.org/html/rfc7517 + */ +@property(nonatomic, readonly) NSURL *jwksURL; + +/*! @brief RECOMMENDED. URL of the OP's Dynamic Client Registration Endpoint. + @remarks registration_endpoint + @seealso http://openid.net/specs/openid-connect-registration-1_0.html + */ +@property(nonatomic, readonly, nullable) NSURL *registrationEndpoint; + +/* @brief OPTIONAL. URL of the OP's RP-Initiated Logout endpoint. + @remarks end_session_endpoint + @seealso http://openid.net/specs/openid-connect-session-1_0.html#OPMetadata + */ +@property(nonatomic, readonly, nullable) NSURL *endSessionEndpoint; + +/*! @brief RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that + this server supports. The server MUST support the openid scope value. Servers MAY choose not + to advertise some supported scope values even when this parameter is used, although those + defined in [OpenID.Core] SHOULD be listed, if supported. + @remarks scopes_supported + @seealso http://tools.ietf.org/html/rfc6749#section-3.3 + */ +@property(nonatomic, readonly, nullable) NSArray *scopesSupported; + +/*! @brief REQUIRED. JSON array containing a list of the OAuth 2.0 @c response_type values that this + OP supports. Dynamic OpenID Providers MUST support the @c code, @c id_token, and the token + @c id_token Response Type values. + @remarks response_types_supported + */ +@property(nonatomic, readonly) NSArray *responseTypesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the OAuth 2.0 @c response_mode values that this + OP supports, as specified in OAuth 2.0 Multiple Response Type Encoding Practices. If + omitted, the default for Dynamic OpenID Providers is @c ["query", "fragment"]. + @remarks response_modes_supported + @seealso http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html + */ +@property(nonatomic, readonly, nullable) NSArray *responseModesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the OAuth 2.0 Grant Type values that this OP + supports. Dynamic OpenID Providers MUST support the @c authorization_code and @c implicit + Grant Type values and MAY support other Grant Types. If omitted, the default value is + @c ["authorization_code", "implicit"]. + @remarks grant_types_supported + */ +@property(nonatomic, readonly, nullable) NSArray *grantTypesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the Authentication Context Class References + that this OP supports. + @remarks acr_values_supported + */ +@property(nonatomic, readonly, nullable) NSArray *acrValuesSupported; + +/*! @brief REQUIRED. JSON array containing a list of the Subject Identifier types that this OP + supports. Valid types include @c pairwise and @c public. + @remarks subject_types_supported + */ +@property(nonatomic, readonly) NSArray *subjectTypesSupported; + +/*! @brief REQUIRED. JSON array containing a list of the JWS signing algorithms (@c alg values) + supported by the OP for the ID Token to encode the Claims in a JWT. The algorithm @c RS256 + MUST be included. The value @c none MAY be supported, but MUST NOT be used unless the + Response Type used returns no ID Token from the Authorization Endpoint (such as when using + the Authorization Code Flow). + @remarks id_token_signing_alg_values_supported + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly) NSArray *IDTokenSigningAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c alg values) + supported by the OP for the ID Token to encode the Claims in a JWT. + @remarks id_token_encryption_alg_values_supported + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *IDTokenEncryptionAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values) + supported by the OP for the ID Token to encode the Claims in a JWT. + @remarks id_token_encryption_enc_values_supported + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *IDTokenEncryptionEncodingValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values) + supported by the UserInfo Endpoint to encode the Claims in a JWT. The value none MAY be + included. + @remarks userinfo_signing_alg_values_supported + @seealso https://tools.ietf.org/html/rfc7515 + @seealso https://tools.ietf.org/html/rfc7518 + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *userinfoSigningAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) + supported by the UserInfo Endpoint to encode the Claims in a JWT. + @remarks userinfo_encryption_alg_values_supported + @seealso https://tools.ietf.org/html/rfc7516 + @seealso https://tools.ietf.org/html/rfc7518 + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *userinfoEncryptionAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values) + supported by the UserInfo Endpoint to encode the Claims in a JWT. + @remarks userinfo_encryption_enc_values_supported + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *userinfoEncryptionEncodingValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values) + supported by the OP for Request Objects, which are described in Section 6.1 of OpenID + Connect Core 1.0. These algorithms are used both when the Request Object is passed by value + (using the request parameter) and when it is passed by reference (using the @c request_uri + parameter). Servers SHOULD support @c none and @c RS256. + @remarks request_object_signing_alg_values_supported + @seealso http://openid.net/specs/openid-connect-core-1_0.html + */ +@property(nonatomic, readonly, nullable) + NSArray *requestObjectSigningAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c alg values) + supported by the OP for Request Objects. These algorithms are used both when the Request + Object is passed by value and when it is passed by reference. + @remarks request_object_encryption_alg_values_supported + */ +@property(nonatomic, readonly, nullable) + NSArray *requestObjectEncryptionAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWE encryption algorithms (@c enc values) + supported by the OP for Request Objects. These algorithms are used both when the Request + Object is passed by value and when it is passed by reference. + @remarks request_object_encryption_enc_values_supported + */ +@property(nonatomic, readonly, nullable) + NSArray *requestObjectEncryptionEncodingValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of Client Authentication methods supported by this + Token Endpoint. The options are @c client_secret_post, @c client_secret_basic, + @c client_secret_jwt, and @c private_key_jwt, as described in Section 9 of OpenID Connect + Core 1.0. Other authentication methods MAY be defined by extensions. If omitted, the default + is @c client_secret_basic -- the HTTP Basic Authentication Scheme specified in Section 2.3.1 + of OAuth 2.0. + @remarks token_endpoint_auth_methods_supported + @seealso http://openid.net/specs/openid-connect-core-1_0.html + @seealso http://tools.ietf.org/html/rfc6749#section-2.3.1 + */ +@property(nonatomic, readonly, nullable) NSArray *tokenEndpointAuthMethodsSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the JWS signing algorithms (@c alg values) + supported by the Token Endpoint for the signature on the JWT used to authenticate the Client + at the Token Endpoint for the @c private_key_jwt and @c client_secret_jwt authentication + methods. Servers SHOULD support @c RS256. The value @c none MUST NOT be used. + @remarks token_endpoint_auth_signing_alg_values_supported + @seealso https://tools.ietf.org/html/rfc7519 + */ +@property(nonatomic, readonly, nullable) + NSArray *tokenEndpointAuthSigningAlgorithmValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the @c display parameter values that the OpenID + Provider supports. These values are described in Section 3.1.2.1 of OpenID Connect Core 1.0. + @remarks display_values_supported + @seealso http://openid.net/specs/openid-connect-core-1_0.html + */ +@property(nonatomic, readonly, nullable) NSArray *displayValuesSupported; + +/*! @brief OPTIONAL. JSON array containing a list of the Claim Types that the OpenID Provider + supports. These Claim Types are described in Section 5.6 of OpenID Connect Core 1.0. Values + defined by this specification are @c normal, @c aggregated, and @c distributed. If omitted, + the implementation supports only @c normal Claims. + @remarks claim_types_supported + @seealso http://openid.net/specs/openid-connect-core-1_0.html + */ +@property(nonatomic, readonly, nullable) NSArray *claimTypesSupported; + +/*! @brief RECOMMENDED. JSON array containing a list of the Claim Names of the Claims that the + OpenID Provider MAY be able to supply values for. Note that for privacy or other reasons, + this might not be an exhaustive list. + @remarks claims_supported + */ +@property(nonatomic, readonly, nullable) NSArray *claimsSupported; + +/*! @brief OPTIONAL. URL of a page containing human-readable information that developers might want + or need to know when using the OpenID Provider. In particular, if the OpenID Provider does + not support Dynamic Client Registration, then information on how to register Clients needs + to be provided in this documentation. + @remarks service_documentation + */ +@property(nonatomic, readonly, nullable) NSURL *serviceDocumentation; + +/*! @brief OPTIONAL. Languages and scripts supported for values in Claims being returned, + represented as a JSON array of BCP47 language tag values. Not all languages and scripts are + necessarily supported for all Claim values. + @remarks claims_locales_supported + @seealso http://tools.ietf.org/html/rfc5646 + */ +@property(nonatomic, readonly, nullable) NSArray *claimsLocalesSupported; + +/*! @brief OPTIONAL. Languages and scripts supported for the user interface, represented as a JSON + array of BCP47 language tag values. + @remarks ui_locales_supported + @seealso http://tools.ietf.org/html/rfc5646 + */ +@property(nonatomic, readonly, nullable) NSArray *UILocalesSupported; + +/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter, + with @c true indicating support. If omitted, the default value is @c false. + @remarks claims_parameter_supported + */ +@property(nonatomic, readonly) BOOL claimsParameterSupported; + +/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter, + with @c true indicating support. If omitted, the default value is @c false. + @remarks request_parameter_supported + */ +@property(nonatomic, readonly) BOOL requestParameterSupported; + +/*! @brief OPTIONAL. Boolean value specifying whether the OP supports use of the @c request_uri + parameter, with true indicating support. If omitted, the default value is @c true. + @remarks request_uri_parameter_supported + */ +@property(nonatomic, readonly) BOOL requestURIParameterSupported; + +/*! @brief OPTIONAL. Boolean value specifying whether the OP requires any @c request_uri values used + to be pre-registered using the @c request_uris registration parameter. Pre-registration is + REQUIRED when the value is @c true. If omitted, the default value is @c false. + @remarks require_request_uri_registration + */ +@property(nonatomic, readonly) BOOL requireRequestURIRegistration; + +/*! @brief OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to + read about the OP's requirements on how the Relying Party can use the data provided by the + OP. The registration process SHOULD display this URL to the person registering the Client if + it is given. + @remarks op_policy_uri + */ +@property(nonatomic, readonly, nullable) NSURL *OPPolicyURI; + +/*! @brief OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to + read about OpenID Provider's terms of service. The registration process SHOULD display this + URL to the person registering the Client if it is given. + @remarks op_tos_uri + */ +@property(nonatomic, readonly, nullable) NSURL *OPTosURI; + +/*! @internal + @brief Unavailable. Please use @c initWithDictionary:error:, @c initWithJSON:error, or the + @c serviceDiscoveryWithURL:callback: factory method. + */ +- (nonnull instancetype)init NS_UNAVAILABLE; + +/*! @brief Decodes a OpenID Connect Discovery 1.0 JSON document. + @param serviceDiscoveryJSON An OpenID Connect Service Discovery document. + @param error If a required field is missing from the dictionary, an error with domain + @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be + returned. + */ +- (nullable instancetype)initWithJSON:(NSString *)serviceDiscoveryJSON + error:(NSError **_Nullable)error; + +/*! @brief Decodes a OpenID Connect Discovery 1.0 JSON document. + @param serviceDiscoveryJSONData An OpenID Connect Service Discovery document. + @param error If a required field is missing from the dictionary, an error with domain + @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be + returned. + */ +- (nullable instancetype)initWithJSONData:(NSData *)serviceDiscoveryJSONData + error:(NSError **_Nullable)error; + +/*! @brief Designated initializer. The dictionary keys should match the keys defined in the OpenID + Connect Discovery 1.0 standard for OpenID Provider Metadata. + @param serviceDiscoveryDictionary A dictionary representing an OpenID Connect Service Discovery + document. + @param error If a required field is missing from the dictionary, an error with domain + @c ::OIDGeneralErrorDomain and code @c ::OIDErrorCodeInvalidDiscoveryDocument will be + returned. + */ +- (nullable instancetype)initWithDictionary:(NSDictionary *)serviceDiscoveryDictionary + error:(NSError **_Nullable)error NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.m new file mode 100644 index 00000000..ca81108a --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDServiceDiscovery.m @@ -0,0 +1,362 @@ +/*! @file OIDServiceDiscovery.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDServiceDiscovery.h" + +#import "OIDDefines.h" +#import "OIDErrorUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! Field keys associated with an OpenID Connect Discovery Document. */ +static NSString *const kIssuerKey = @"issuer"; +static NSString *const kAuthorizationEndpointKey = @"authorization_endpoint"; +static NSString *const kTokenEndpointKey = @"token_endpoint"; +static NSString *const kUserinfoEndpointKey = @"userinfo_endpoint"; +static NSString *const kJWKSURLKey = @"jwks_uri"; +static NSString *const kRegistrationEndpointKey = @"registration_endpoint"; +static NSString *const kEndSessionEndpointKey = @"end_session_endpoint"; +static NSString *const kScopesSupportedKey = @"scopes_supported"; +static NSString *const kResponseTypesSupportedKey = @"response_types_supported"; +static NSString *const kResponseModesSupportedKey = @"response_modes_supported"; +static NSString *const kGrantTypesSupportedKey = @"grant_types_supported"; +static NSString *const kACRValuesSupportedKey = @"acr_values_supported"; +static NSString *const kSubjectTypesSupportedKey = @"subject_types_supported"; +static NSString *const kIDTokenSigningAlgorithmValuesSupportedKey = + @"id_token_signing_alg_values_supported"; +static NSString *const kIDTokenEncryptionAlgorithmValuesSupportedKey = + @"id_token_encryption_alg_values_supported"; +static NSString *const kIDTokenEncryptionEncodingValuesSupportedKey = + @"id_token_encryption_enc_values_supported"; +static NSString *const kUserinfoSigningAlgorithmValuesSupportedKey = + @"userinfo_signing_alg_values_supported"; +static NSString *const kUserinfoEncryptionAlgorithmValuesSupportedKey = + @"userinfo_encryption_alg_values_supported"; +static NSString *const kUserinfoEncryptionEncodingValuesSupportedKey = + @"userinfo_encryption_enc_values_supported"; +static NSString *const kRequestObjectSigningAlgorithmValuesSupportedKey = + @"request_object_signing_alg_values_supported"; +static NSString *const kRequestObjectEncryptionAlgorithmValuesSupportedKey = + @"request_object_encryption_alg_values_supported"; +static NSString *const kRequestObjectEncryptionEncodingValuesSupported = + @"request_object_encryption_enc_values_supported"; +static NSString *const kTokenEndpointAuthMethodsSupportedKey = + @"token_endpoint_auth_methods_supported"; +static NSString *const kTokenEndpointAuthSigningAlgorithmValuesSupportedKey = + @"token_endpoint_auth_signing_alg_values_supported"; +static NSString *const kDisplayValuesSupportedKey = @"display_values_supported"; +static NSString *const kClaimTypesSupportedKey = @"claim_types_supported"; +static NSString *const kClaimsSupportedKey = @"claims_supported"; +static NSString *const kServiceDocumentationKey = @"service_documentation"; +static NSString *const kClaimsLocalesSupportedKey = @"claims_locales_supported"; +static NSString *const kUILocalesSupportedKey = @"ui_locales_supported"; +static NSString *const kClaimsParameterSupportedKey = @"claims_parameter_supported"; +static NSString *const kRequestParameterSupportedKey = @"request_parameter_supported"; +static NSString *const kRequestURIParameterSupportedKey = @"request_uri_parameter_supported"; +static NSString *const kRequireRequestURIRegistrationKey = @"require_request_uri_registration"; +static NSString *const kOPPolicyURIKey = @"op_policy_uri"; +static NSString *const kOPTosURIKey = @"op_tos_uri"; + +@implementation OIDServiceDiscovery { + NSDictionary *_discoveryDictionary; +} + +- (nonnull instancetype)init OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithDictionary:error:)) + +- (nullable instancetype)initWithJSON:(NSString *)serviceDiscoveryJSON error:(NSError **)error { + NSData *jsonData = [serviceDiscoveryJSON dataUsingEncoding:NSUTF8StringEncoding]; + return [self initWithJSONData:jsonData error:error]; +} + +- (nullable instancetype)initWithJSONData:(NSData *)serviceDiscoveryJSONData + error:(NSError **_Nullable)error { + NSError *jsonError; + NSDictionary *json = + [NSJSONSerialization JSONObjectWithData:serviceDiscoveryJSONData options:0 error:&jsonError]; + if (!json || jsonError) { + *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeJSONDeserializationError + underlyingError:jsonError + description:jsonError.localizedDescription]; + return nil; + } + if (![json isKindOfClass:[NSDictionary class]]) { + *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument + underlyingError:nil + description:@"Discovery document isn't a dictionary"]; + return nil; + } + + return [self initWithDictionary:json error:error]; +} + +- (nullable instancetype)initWithDictionary:(NSDictionary *)serviceDiscoveryDictionary + error:(NSError **_Nullable)error { + if (![[self class] dictionaryHasRequiredFields:serviceDiscoveryDictionary error:error]) { + return nil; + } + self = [super init]; + if (self) { + _discoveryDictionary = [serviceDiscoveryDictionary copy]; + } + return self; +} + +#pragma mark - + +/*! @brief Checks to see if the specified dictionary contains the required fields. + @discussion This test is not meant to provide semantic analysis of the document (eg. fields + where the value @c none is not an allowed option would not cause this method to fail if + their value was @c none.) We are just testing to make sure we can meet the nullability + contract we promised in the header. + */ ++ (BOOL)dictionaryHasRequiredFields:(NSDictionary *)dictionary + error:(NSError **_Nullable)error { + static NSString *const kMissingFieldErrorText = @"Missing field: %@"; + static NSString *const kInvalidURLFieldErrorText = @"Invalid URL: %@"; + + NSArray *requiredFields = @[ + kIssuerKey, + kAuthorizationEndpointKey, + kTokenEndpointKey, + kJWKSURLKey, + kResponseTypesSupportedKey, + kSubjectTypesSupportedKey, + kIDTokenSigningAlgorithmValuesSupportedKey + ]; + + for (NSString *field in requiredFields) { + if (!dictionary[field]) { + if (error) { + NSString *errorText = [NSString stringWithFormat:kMissingFieldErrorText, field]; + *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument + underlyingError:nil + description:errorText]; + } + return NO; + } + } + + // Check required URL fields are valid URLs. + NSArray *requiredURLFields = @[ + kIssuerKey, + kTokenEndpointKey, + kJWKSURLKey + ]; + + for (NSString *field in requiredURLFields) { + if (![NSURL URLWithString:dictionary[field]]) { + if (error) { + NSString *errorText = [NSString stringWithFormat:kInvalidURLFieldErrorText, field]; + *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeInvalidDiscoveryDocument + underlyingError:nil + description:errorText]; + } + return NO; + } + } + + return YES; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSError *error; + NSDictionary *dictionary = [[NSDictionary alloc] initWithCoder:aDecoder]; + self = [self initWithDictionary:dictionary error:&error]; + if (error) { + return nil; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [_discoveryDictionary encodeWithCoder:aCoder]; +} + +#pragma mark - Properties + +- (NSDictionary *)discoveryDictionary { + return _discoveryDictionary; +} + +- (NSURL *)issuer { + return [NSURL URLWithString:_discoveryDictionary[kIssuerKey]]; +} + +- (NSURL *)authorizationEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kAuthorizationEndpointKey]]; +} + +- (NSURL *)tokenEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kTokenEndpointKey]]; +} + +- (nullable NSURL *)userinfoEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kUserinfoEndpointKey]]; +} + +- (NSURL *)jwksURL { + return [NSURL URLWithString:_discoveryDictionary[kJWKSURLKey]]; +} + +- (nullable NSURL *)registrationEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kRegistrationEndpointKey]]; +} + +- (nullable NSURL *)endSessionEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kEndSessionEndpointKey]]; +} + +- (nullable NSArray *)scopesSupported { + return _discoveryDictionary[kScopesSupportedKey]; +} + +- (NSArray *)responseTypesSupported { + return _discoveryDictionary[kResponseTypesSupportedKey]; +} + +- (nullable NSArray *)responseModesSupported { + return _discoveryDictionary[kResponseModesSupportedKey]; +} + +- (nullable NSArray *)grantTypesSupported { + return _discoveryDictionary[kGrantTypesSupportedKey]; +} + +- (nullable NSArray *)acrValuesSupported { + return _discoveryDictionary[kACRValuesSupportedKey]; +} + +- (NSArray *)subjectTypesSupported { + return _discoveryDictionary[kSubjectTypesSupportedKey]; +} + +- (NSArray *) IDTokenSigningAlgorithmValuesSupported { + return _discoveryDictionary[kIDTokenSigningAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *)IDTokenEncryptionAlgorithmValuesSupported { + return _discoveryDictionary[kIDTokenEncryptionAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *)IDTokenEncryptionEncodingValuesSupported { + return _discoveryDictionary[kIDTokenEncryptionEncodingValuesSupportedKey]; +} + +- (nullable NSArray *)userinfoSigningAlgorithmValuesSupported { + return _discoveryDictionary[kUserinfoSigningAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *)userinfoEncryptionAlgorithmValuesSupported { + return _discoveryDictionary[kUserinfoEncryptionAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *)userinfoEncryptionEncodingValuesSupported { + return _discoveryDictionary[kUserinfoEncryptionEncodingValuesSupportedKey]; +} + +- (nullable NSArray *)requestObjectSigningAlgorithmValuesSupported { + return _discoveryDictionary[kRequestObjectSigningAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *) requestObjectEncryptionAlgorithmValuesSupported { + return _discoveryDictionary[kRequestObjectEncryptionAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *) requestObjectEncryptionEncodingValuesSupported { + return _discoveryDictionary[kRequestObjectEncryptionEncodingValuesSupported]; +} + +- (nullable NSArray *)tokenEndpointAuthMethodsSupported { + return _discoveryDictionary[kTokenEndpointAuthMethodsSupportedKey]; +} + +- (nullable NSArray *)tokenEndpointAuthSigningAlgorithmValuesSupported { + return _discoveryDictionary[kTokenEndpointAuthSigningAlgorithmValuesSupportedKey]; +} + +- (nullable NSArray *)displayValuesSupported { + return _discoveryDictionary[kDisplayValuesSupportedKey]; +} + +- (nullable NSArray *)claimTypesSupported { + return _discoveryDictionary[kClaimTypesSupportedKey]; +} + +- (nullable NSArray *)claimsSupported { + return _discoveryDictionary[kClaimsSupportedKey]; +} + +- (nullable NSURL *)serviceDocumentation { + return [NSURL URLWithString:_discoveryDictionary[kServiceDocumentationKey]]; +} + +- (nullable NSArray *)claimsLocalesSupported { + return _discoveryDictionary[kClaimsLocalesSupportedKey]; +} + +- (nullable NSArray *)UILocalesSupported { + return _discoveryDictionary[kUILocalesSupportedKey]; +} + +- (BOOL)claimsParameterSupported { + return [_discoveryDictionary[kClaimsParameterSupportedKey] boolValue]; +} + +- (BOOL)requestParameterSupported { + return [_discoveryDictionary[kRequestParameterSupportedKey] boolValue]; +} + +- (BOOL)requestURIParameterSupported { + // Default is true/YES. + if (!_discoveryDictionary[kRequestURIParameterSupportedKey]) { + return YES; + } + return [_discoveryDictionary[kRequestURIParameterSupportedKey] boolValue]; +} + +- (BOOL)requireRequestURIRegistration { + return [_discoveryDictionary[kRequireRequestURIRegistrationKey] boolValue]; +} + +- (nullable NSURL *)OPPolicyURI { + return [NSURL URLWithString:_discoveryDictionary[kOPPolicyURIKey]]; +} + +- (nullable NSURL *)OPTosURI { + return [NSURL URLWithString:_discoveryDictionary[kOPTosURIKey]]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.h new file mode 100644 index 00000000..00e0c6e2 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.h @@ -0,0 +1,162 @@ +/*! @file OIDTokenRequest.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +// This file only declares string constants useful for constructing a @c OIDTokenRequest, so it is +// imported here for convenience. +#import "OIDGrantTypes.h" + +@class OIDAuthorizationResponse; +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents a token request. + @see https://tools.ietf.org/html/rfc6749#section-3.2 + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +@interface OIDTokenRequest : NSObject + +/*! @brief The service's configuration. + @remarks This configuration specifies how to connect to a particular OAuth provider. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @brief The type of token being sent to the token endpoint, i.e. "authorization_code" for the + authorization code exchange, or "refresh_token" for an access token refresh request. + @remarks grant_type + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + @see https://www.google.com/url?sa=D&q=https%3A%2F%2Ftools.ietf.org%2Fhtml%2Frfc6749%23section-6 + */ +@property(nonatomic, readonly) NSString *grantType; + +/*! @brief The authorization code received from the authorization server. + @remarks code + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +@property(nonatomic, readonly, nullable) NSString *authorizationCode; + +/*! @brief The client's redirect URI. + @remarks redirect_uri + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +@property(nonatomic, readonly, nullable) NSURL *redirectURL; + +/*! @brief The client identifier. + @remarks client_id + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +@property(nonatomic, readonly) NSString *clientID; + +/*! @brief The client secret. + @remarks client_secret + @see https://tools.ietf.org/html/rfc6749#section-2.3.1 + */ +@property(nonatomic, readonly, nullable) NSString *clientSecret; + +/*! @brief The value of the scope parameter is expressed as a list of space-delimited, + case-sensitive strings. + @remarks scope + @see https://tools.ietf.org/html/rfc6749#section-3.3 + */ +@property(nonatomic, readonly, nullable) NSString *scope; + +/*! @brief The refresh token, which can be used to obtain new access tokens using the same + authorization grant. + @remarks refresh_token + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *refreshToken; + +/*! @brief The PKCE code verifier used to redeem the authorization code. + @remarks code_verifier + @see https://tools.ietf.org/html/rfc7636#section-4.3 + */ +@property(nonatomic, readonly, nullable) NSString *codeVerifier; + +/*! @brief The client's additional token request parameters. + */ +@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters; + +/*! @internal + @brief Unavailable. Please use + initWithConfiguration:grantType:code:redirectURL:clientID:additionalParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @param configuration The service's configuration. + @param grantType the type of token being sent to the token endpoint, i.e. "authorization_code" + for the authorization code exchange, or "refresh_token" for an access token refresh request. + @see OIDGrantTypes.h + @param code The authorization code received from the authorization server. + @param redirectURL The client's redirect URI. + @param clientID The client identifier. + @param clientSecret The client secret. + @param scopes An array of scopes to combine into a single scope string per the OAuth2 spec. + @param refreshToken The refresh token. + @param codeVerifier The PKCE code verifier. + @param additionalParameters The client's additional token request parameters. + */ +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + grantType:(NSString *)grantType + authorizationCode:(nullable NSString *)code + redirectURL:(nullable NSURL *)redirectURL + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scopes:(nullable NSArray *)scopes + refreshToken:(nullable NSString *)refreshToken + codeVerifier:(nullable NSString *)codeVerifier + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Designated initializer. + @param configuration The service's configuration. + @param grantType the type of token being sent to the token endpoint, i.e. "authorization_code" + for the authorization code exchange, or "refresh_token" for an access token refresh request. + @see OIDGrantTypes.h + @param code The authorization code received from the authorization server. + @param redirectURL The client's redirect URI. + @param clientID The client identifier. + @param clientSecret The client secret. + @param scope The value of the scope parameter is expressed as a list of space-delimited, + case-sensitive strings. + @param refreshToken The refresh token. + @param codeVerifier The PKCE code verifier. + @param additionalParameters The client's additional token request parameters. + */ +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + grantType:(NSString *)grantType + authorizationCode:(nullable NSString *)code + redirectURL:(nullable NSURL *)redirectURL + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scope:(nullable NSString *)scope + refreshToken:(nullable NSString *)refreshToken + codeVerifier:(nullable NSString *)codeVerifier + additionalParameters:(nullable NSDictionary *)additionalParameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Constructs an @c NSURLRequest representing the token request. + @return An @c NSURLRequest representing the token request. + */ +- (NSURLRequest *)URLRequest; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.m new file mode 100644 index 00000000..bd27dd48 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenRequest.m @@ -0,0 +1,307 @@ +/*! @file OIDTokenRequest.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDTokenRequest.h" + +#import "OIDDefines.h" +#import "OIDError.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDURLQueryComponent.h" +#import "OIDTokenUtilities.h" + +/*! @brief The key for the @c configuration property for @c NSSecureCoding + */ +static NSString *const kConfigurationKey = @"configuration"; + +/*! @brief Key used to encode the @c grantType property for @c NSSecureCoding + */ +static NSString *const kGrantTypeKey = @"grant_type"; + +/*! @brief The key for the @c authorizationCode property for @c NSSecureCoding. + */ +static NSString *const kAuthorizationCodeKey = @"code"; + +/*! @brief Key used to encode the @c clientID property for @c NSSecureCoding + */ +static NSString *const kClientIDKey = @"client_id"; + +/*! @brief Key used to encode the @c clientSecret property for @c NSSecureCoding + */ +static NSString *const kClientSecretKey = @"client_secret"; + +/*! @brief Key used to encode the @c redirectURL property for @c NSSecureCoding + */ +static NSString *const kRedirectURLKey = @"redirect_uri"; + +/*! @brief Key used to encode the @c scopes property for @c NSSecureCoding + */ +static NSString *const kScopeKey = @"scope"; + +/*! @brief Key used to encode the @c refreshToken property for @c NSSecureCoding + */ +static NSString *const kRefreshTokenKey = @"refresh_token"; + +/*! @brief Key used to encode the @c codeVerifier property for @c NSSecureCoding and to build the + request URL. + */ +static NSString *const kCodeVerifierKey = @"code_verifier"; + +/*! @brief Key used to encode the @c additionalParameters property for + @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +@implementation OIDTokenRequest + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER( + @selector(initWithConfiguration: + grantType: + authorizationCode: + redirectURL: + clientID: + clientSecret: + scope: + refreshToken: + codeVerifier: + additionalParameters:) + ) + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + grantType:(NSString *)grantType + authorizationCode:(nullable NSString *)code + redirectURL:(nullable NSURL *)redirectURL + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scopes:(nullable NSArray *)scopes + refreshToken:(nullable NSString *)refreshToken + codeVerifier:(nullable NSString *)codeVerifier + additionalParameters:(nullable NSDictionary *)additionalParameters { + return [self initWithConfiguration:configuration + grantType:grantType + authorizationCode:code + redirectURL:redirectURL + clientID:clientID + clientSecret:clientSecret + scope:[OIDScopeUtilities scopesWithArray:scopes] + refreshToken:refreshToken + codeVerifier:(NSString *)codeVerifier + additionalParameters:additionalParameters]; +} + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + grantType:(NSString *)grantType + authorizationCode:(nullable NSString *)code + redirectURL:(nullable NSURL *)redirectURL + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret + scope:(nullable NSString *)scope + refreshToken:(nullable NSString *)refreshToken + codeVerifier:(nullable NSString *)codeVerifier + additionalParameters:(nullable NSDictionary *)additionalParameters { + self = [super init]; + if (self) { + _configuration = [configuration copy]; + _grantType = [grantType copy]; + _authorizationCode = [code copy]; + _redirectURL = [redirectURL copy]; + _clientID = [clientID copy]; + _clientSecret = [clientSecret copy]; + _scope = [scope copy]; + _refreshToken = [refreshToken copy]; + _codeVerifier = [codeVerifier copy]; + _additionalParameters = + [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES]; + + // Additional validation for the authorization_code grant type + if ([_grantType isEqual:OIDGrantTypeAuthorizationCode]) { + // redirect URI must not be nil + if (!_redirectURL) { + [NSException raise:OIDOAuthExceptionInvalidTokenRequestNullRedirectURL + format:@"%@", OIDOAuthExceptionInvalidTokenRequestNullRedirectURL, nil]; + + } + } + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDServiceConfiguration *configuration = + [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] + forKey:kConfigurationKey]; + NSString *grantType = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGrantTypeKey]; + NSString *code = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAuthorizationCodeKey]; + NSString *clientID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientIDKey]; + NSString *clientSecret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kClientSecretKey]; + NSString *scope = [aDecoder decodeObjectOfClass:[NSString class] forKey:kScopeKey]; + NSString *refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey]; + NSString *codeVerifier = [aDecoder decodeObjectOfClass:[NSString class] forKey:kCodeVerifierKey]; + NSURL *redirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kRedirectURLKey]; + NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ + [NSDictionary class], + [NSString class] + ]]; + NSDictionary *additionalParameters = + [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses + forKey:kAdditionalParametersKey]; + self = [self initWithConfiguration:configuration + grantType:grantType + authorizationCode:code + redirectURL:redirectURL + clientID:clientID + clientSecret:clientSecret + scope:scope + refreshToken:refreshToken + codeVerifier:codeVerifier + additionalParameters:additionalParameters]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_configuration forKey:kConfigurationKey]; + [aCoder encodeObject:_grantType forKey:kGrantTypeKey]; + [aCoder encodeObject:_authorizationCode forKey:kAuthorizationCodeKey]; + [aCoder encodeObject:_clientID forKey:kClientIDKey]; + [aCoder encodeObject:_clientSecret forKey:kClientSecretKey]; + [aCoder encodeObject:_redirectURL forKey:kRedirectURLKey]; + [aCoder encodeObject:_scope forKey:kScopeKey]; + [aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey]; + [aCoder encodeObject:_codeVerifier forKey:kCodeVerifierKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + NSURLRequest *request = self.URLRequest; + NSString *requestBody = + [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]; + return [NSString stringWithFormat:@"<%@: %p, request: >", + NSStringFromClass([self class]), + (void *)self, + request.URL, + requestBody]; +} + +#pragma mark - + +/*! @brief Constructs the request URI. + @return A URL representing the token request. + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +- (NSURL *)tokenRequestURL { + return _configuration.tokenEndpoint; +} + +/*! @brief Constructs the request body data by combining the request parameters using the + "application/x-www-form-urlencoded" format. + @return The data to pass to the token request URL. + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +- (OIDURLQueryComponent *)tokenRequestBody { + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init]; + + // Add parameters, as applicable. + if (_grantType) { + [query addParameter:kGrantTypeKey value:_grantType]; + } + if (_scope) { + [query addParameter:kScopeKey value:_scope]; + } + if (_redirectURL) { + [query addParameter:kRedirectURLKey value:_redirectURL.absoluteString]; + } + if (_refreshToken) { + [query addParameter:kRefreshTokenKey value:_refreshToken]; + } + if (_authorizationCode) { + [query addParameter:kAuthorizationCodeKey value:_authorizationCode]; + } + if (_codeVerifier) { + [query addParameter:kCodeVerifierKey value:_codeVerifier]; + } + + // Add any additional parameters the client has specified. + [query addParameters:_additionalParameters]; + + return query; +} + +- (NSURLRequest *)URLRequest { + static NSString *const kHTTPPost = @"POST"; + static NSString *const kHTTPContentTypeHeaderKey = @"Content-Type"; + static NSString *const kHTTPContentTypeHeaderValue = + @"application/x-www-form-urlencoded; charset=UTF-8"; + + NSURL *tokenRequestURL = [self tokenRequestURL]; + NSMutableURLRequest *URLRequest = [[NSURLRequest requestWithURL:tokenRequestURL] mutableCopy]; + URLRequest.HTTPMethod = kHTTPPost; + [URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey]; + + OIDURLQueryComponent *bodyParameters = [self tokenRequestBody]; + NSMutableDictionary *httpHeaders = [[NSMutableDictionary alloc] init]; + + if (_clientSecret) { + // The client id and secret are encoded using the "application/x-www-form-urlencoded" + // encoding algorithm per RFC 6749 Section 2.3.1. + // https://tools.ietf.org/html/rfc6749#section-2.3.1 + NSString *encodedClientID = [OIDTokenUtilities formUrlEncode:_clientID]; + NSString *encodedClientSecret = [OIDTokenUtilities formUrlEncode:_clientSecret]; + + NSString *credentials = + [NSString stringWithFormat:@"%@:%@", encodedClientID, encodedClientSecret]; + NSData *plainData = [credentials dataUsingEncoding:NSUTF8StringEncoding]; + NSString *basicAuth = [plainData base64EncodedStringWithOptions:kNilOptions]; + + NSString *authValue = [NSString stringWithFormat:@"Basic %@", basicAuth]; + [httpHeaders setObject:authValue forKey:@"Authorization"]; + } else { + [bodyParameters addParameter:kClientIDKey value:_clientID]; + } + + // Constructs request with the body string and headers. + NSString *bodyString = [bodyParameters URLEncodedParameters]; + NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding]; + URLRequest.HTTPBody = body; + + for (id header in httpHeaders) { + [URLRequest setValue:httpHeaders[header] forHTTPHeaderField:header]; + } + + return URLRequest; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.h new file mode 100644 index 00000000..b446e944 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.h @@ -0,0 +1,110 @@ +/*! @file OIDTokenResponse.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDTokenRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents the response to an token request. + @see https://tools.ietf.org/html/rfc6749#section-3.2 + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + */ +@interface OIDTokenResponse : NSObject + +/*! @brief The request which was serviced. + */ +@property(nonatomic, readonly) OIDTokenRequest *request; + +/*! @brief The access token generated by the authorization server. + @remarks access_token + @see https://tools.ietf.org/html/rfc6749#section-4.1.4 + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *accessToken; + +/*! @brief The approximate expiration date & time of the access token. + @remarks expires_in + @seealso OIDTokenResponse.accessToken + @see https://tools.ietf.org/html/rfc6749#section-4.1.4 + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSDate *accessTokenExpirationDate; + +/*! @brief Typically "Bearer" when present. Otherwise, another token_type value that the Client has + negotiated with the Authorization Server. + @remarks token_type + @see https://tools.ietf.org/html/rfc6749#section-4.1.4 + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *tokenType; + +/*! @brief ID Token value associated with the authenticated session. Always present for the + authorization code grant exchange when OpenID Connect is used, optional for responses to + access token refresh requests. Note that AppAuth does NOT verify the JWT signature. Users + of AppAuth are encouraged to verifying the JWT signature using the validation library of + their choosing. + @remarks id_token + @see http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse + @see http://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse + @see http://openid.net/specs/openid-connect-core-1_0.html#IDToken + @see https://jwt.io + @discussion @c OIDIDToken can be used to parse the ID Token and extract the claims. As noted, + this class does not verify the JWT signature. +*/ +@property(nonatomic, readonly, nullable) NSString *idToken; + +/*! @brief The refresh token, which can be used to obtain new access tokens using the same + authorization grant + @remarks refresh_token + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *refreshToken; + +/*! @brief The scope of the access token. OPTIONAL, if identical to the scopes requested, otherwise, + REQUIRED. + @remarks scope + @see https://tools.ietf.org/html/rfc6749#section-5.1 + */ +@property(nonatomic, readonly, nullable) NSString *scope; + +/*! @brief Additional parameters returned from the token server. + */ +@property(nonatomic, readonly, nullable) + NSDictionary *> *additionalParameters; + +/*! @internal + @brief Unavailable. Please use initWithParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Designated initializer. + @param request The serviced request. + @param parameters The decoded parameters returned from the Authorization Server. + @remarks Known parameters are extracted from the @c parameters parameter and the normative + properties are populated. Non-normative parameters are placed in the + @c #additionalParameters dictionary. + */ +- (instancetype)initWithRequest:(OIDTokenRequest *)request + parameters:(NSDictionary *> *)parameters + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.m new file mode 100644 index 00000000..6995fb91 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenResponse.m @@ -0,0 +1,163 @@ +/*! @file OIDTokenResponse.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDTokenResponse.h" + +#import "OIDDefines.h" +#import "OIDFieldMapping.h" +#import "OIDTokenRequest.h" +#import "OIDTokenUtilities.h" + +/*! @brief Key used to encode the @c request property for @c NSSecureCoding + */ +static NSString *const kRequestKey = @"request"; + +/*! @brief The key for the @c accessToken property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kAccessTokenKey = @"access_token"; + +/*! @brief The key for the @c accessTokenExpirationDate property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kExpiresInKey = @"expires_in"; + +/*! @brief The key for the @c tokenType property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kTokenTypeKey = @"token_type"; + +/*! @brief The key for the @c idToken property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kIDTokenKey = @"id_token"; + +/*! @brief The key for the @c refreshToken property in the incoming parameters and for + @c NSSecureCoding. + */ +static NSString *const kRefreshTokenKey = @"refresh_token"; + +/*! @brief The key for the @c scope property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kScopeKey = @"scope"; + +/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +@implementation OIDTokenResponse + +/*! @brief Returns a mapping of incoming parameters to instance variables. + @return A mapping of incoming parameters to instance variables. + */ ++ (NSDictionary *)fieldMap { + static NSMutableDictionary *fieldMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fieldMap = [NSMutableDictionary dictionary]; + fieldMap[kAccessTokenKey] = + [[OIDFieldMapping alloc] initWithName:@"_accessToken" type:[NSString class]]; + fieldMap[kExpiresInKey] = + [[OIDFieldMapping alloc] initWithName:@"_accessTokenExpirationDate" + type:[NSDate class] + conversion:[OIDFieldMapping dateSinceNowConversion]]; + fieldMap[kTokenTypeKey] = + [[OIDFieldMapping alloc] initWithName:@"_tokenType" type:[NSString class]]; + fieldMap[kIDTokenKey] = + [[OIDFieldMapping alloc] initWithName:@"_idToken" type:[NSString class]]; + fieldMap[kRefreshTokenKey] = + [[OIDFieldMapping alloc] initWithName:@"_refreshToken" type:[NSString class]]; + fieldMap[kScopeKey] = + [[OIDFieldMapping alloc] initWithName:@"_scope" type:[NSString class]]; + }); + return fieldMap; +} + +#pragma mark - Initializers + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:)) + +- (instancetype)initWithRequest:(OIDTokenRequest *)request + parameters:(NSDictionary *> *)parameters { + self = [super init]; + if (self) { + _request = [request copy]; + NSDictionary *> *additionalParameters = + [OIDFieldMapping remainingParametersWithMap:[[self class] fieldMap] + parameters:parameters + instance:self]; + _additionalParameters = additionalParameters; + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDTokenRequest *request = + [aDecoder decodeObjectOfClass:[OIDTokenRequest class] forKey:kRequestKey]; + self = [self initWithRequest:request parameters:@{ }]; + if (self) { + [OIDFieldMapping decodeWithCoder:aDecoder map:[[self class] fieldMap] instance:self]; + _additionalParameters = [aDecoder decodeObjectOfClasses:[OIDFieldMapping JSONTypes] + forKey:kAdditionalParametersKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [OIDFieldMapping encodeWithCoder:aCoder map:[[self class] fieldMap] instance:self]; + [aCoder encodeObject:_request forKey:kRequestKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, accessToken: \"%@\", accessTokenExpirationDate: %@, " + "tokenType: %@, idToken: \"%@\", refreshToken: \"%@\", " + "scope: \"%@\", additionalParameters: %@, request: %@>", + NSStringFromClass([self class]), + (void *)self, + [OIDTokenUtilities redact:_accessToken], + _accessTokenExpirationDate, + _tokenType, + [OIDTokenUtilities redact:_idToken], + [OIDTokenUtilities redact:_refreshToken], + _scope, + _additionalParameters, + _request]; +} + +#pragma mark - + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.h new file mode 100644 index 00000000..fda89854 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.h @@ -0,0 +1,67 @@ +/*! @file OIDTokenUtilities.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Provides data encoding/decoding methods, random string generators, etc. + */ +@interface OIDTokenUtilities : NSObject + +/*! @internal + @brief Unavailable. This class should not be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Base64url-nopadding encodes the given data. + @param data The input data. + @return The base64url encoded data as a NSString. + @discussion Base64url-nopadding is used in several identity specs such as PKCE and + OpenID Connect. + */ ++ (NSString *)encodeBase64urlNoPadding:(NSData *)data; + +/*! @brief Generates a URL-safe string of random data. + @param size The number of random bytes to encode. NB. the length of the output string will be + greater than the number of random bytes, due to the URL-safe encoding. + @return Random data encoded with base64url. + */ ++ (nullable NSString *)randomURLSafeStringWithSize:(NSUInteger)size; + +/*! @brief SHA256 hashes the input string. + @param inputString The input string. + @return The SHA256 data. + */ ++ (NSData *)sha256:(NSString *)inputString; + +/*! @brief Truncated intput string after first 6 characters followed by ellipses + @param inputString The input string. + @return Truncated string. + */ ++ (nullable NSString *)redact:(nullable NSString *)inputString; + +/*! @brief Form url encode the input string by applying application/x-www-form-urlencoded algorithm + @param inputString The input string. + @return The encoded string. + */ ++ (NSString*)formUrlEncode:(NSString*)inputString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.m new file mode 100644 index 00000000..3280c856 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDTokenUtilities.m @@ -0,0 +1,89 @@ +/*! @file OIDTokenUtilities.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDTokenUtilities.h" + +#import + +/*! @brief String representing the set of characters that are allowed as is for the + application/x-www-form-urlencoded encoding algorithm. + */ +static NSString *const kFormUrlEncodedAllowedCharacters = + @" *-._0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +@implementation OIDTokenUtilities + ++ (NSString *)encodeBase64urlNoPadding:(NSData *)data { + NSString *base64string = [data base64EncodedStringWithOptions:0]; + // converts base64 to base64url + base64string = [base64string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + base64string = [base64string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + // strips padding + base64string = [base64string stringByReplacingOccurrencesOfString:@"=" withString:@""]; + return base64string; +} + ++ (nullable NSString *)randomURLSafeStringWithSize:(NSUInteger)size { + NSMutableData *randomData = [NSMutableData dataWithLength:size]; + int result = SecRandomCopyBytes(kSecRandomDefault, randomData.length, randomData.mutableBytes); + if (result != 0) { + return nil; + } + return [[self class] encodeBase64urlNoPadding:randomData]; +} + ++ (NSData *)sha256:(NSString *)inputString { + NSData *verifierData = [inputString dataUsingEncoding:NSUTF8StringEncoding]; + NSMutableData *sha256Verifier = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(verifierData.bytes, (CC_LONG)verifierData.length, sha256Verifier.mutableBytes); + return sha256Verifier; +} + ++ (NSString *)redact:(NSString *)inputString { + if (inputString == nil) { + return nil; + } + switch(inputString.length){ + case 0: + return @""; + case 1 ... 8: + return @"[redacted]"; + case 9: + default: + return [[inputString substringToIndex:6] stringByAppendingString:@"...[redacted]"]; + } +} + ++ (NSString*)formUrlEncode:(NSString*)inputString { + // https://www.w3.org/TR/html5/sec-forms.html#application-x-www-form-urlencoded-encoding-algorithm + // Following the spec from the above link, application/x-www-form-urlencoded percent encode all + // the characters except *-._A-Za-z0-9 + // Space character is replaced by + in the resulting bytes sequence + if (inputString.length == 0) { + return inputString; + } + NSCharacterSet *allowedCharacters = + [NSCharacterSet characterSetWithCharactersInString:kFormUrlEncodedAllowedCharacters]; + // Percent encode all characters not present in the provided set. + NSString *encodedString = + [inputString stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; + // Replace occurences of space by '+' character + return [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.h new file mode 100644 index 00000000..054b11ea --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.h @@ -0,0 +1,93 @@ +/*! @file OIDURLQueryComponent.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@class OIDAuthorizationRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief If set to YES, will force the iOS 7-only code for @c OIDURLQueryComponent to be used, + even on non-iOS 7 devices and simulators. Useful for testing the iOS 7 code paths on the + simulator. Defaults to NO. + */ +extern BOOL gOIDURLQueryComponentForceIOS7Handling; + +/*! @brief A utility class for creating and parsing URL query components encoded with the + application/x-www-form-urlencoded format. + @description Supports application/x-www-form-urlencoded encoding and decoding, specifically + '+' is replaced with space before percent decoding. For encoding, simply percent encodes + space, as this is valid application/x-www-form-urlencoded. + @see https://tools.ietf.org/html/rfc6749#section-4.1.2 + @see https://tools.ietf.org/html/rfc6749#section-4.1.3 + @see https://tools.ietf.org/html/rfc6749#appendix-B + @see https://url.spec.whatwg.org/#urlencoded-parsing + */ +@interface OIDURLQueryComponent : NSObject + +/*! @brief The parameter names in the query. + */ +@property(nonatomic, readonly) NSArray *parameters; + +/*! @brief The parameters represented as a dictionary. + @remarks All values are @c NSString except for parameters which contain multiple values, in + which case the value is an @c NSArray *. + */ +@property(nonatomic, readonly) NSDictionary *> *dictionaryValue; + +/*! @brief Creates an @c OIDURLQueryComponent by parsing the query string in a URL. + @param URL The URL from which to extract a query component. + */ +- (nullable instancetype)initWithURL:(NSURL *)URL; + +/*! @brief The value (or values) for a named parameter in the query. + @param parameter The parameter name. Case sensitive. + @return The value (or values) for a named parameter in the query. + */ +- (NSArray *)valuesForParameter:(NSString *)parameter; + +/*! @brief Adds a parameter value to the query. + @param parameter The name of the parameter. Case sensitive. + @param value The value to add. + */ +- (void)addParameter:(NSString *)parameter value:(NSString *)value; + +/*! @brief Adds multiple parameters with associated values to the query. + @param parameters The parameter name value pairs to add to the query. + */ +- (void)addParameters:(NSDictionary *)parameters; + +/*! @param URL The URL to add the query component to. + @return The original URL with the query component replaced by the parameters from this query. + */ +- (NSURL *)URLByReplacingQueryInURL:(NSURL *)URL; + +/*! @brief Builds an x-www-form-urlencoded string representing the parameters. + @return The x-www-form-urlencoded string representing the parameters. + */ +- (NSString *)URLEncodedParameters; + +/*! @brief A NSMutableCharacterSet containing allowed characters in URL parameter values (that is + the "value" part of "?key=value"). This has less allowed characters than + @c URLQueryAllowedCharacterSet, as the query component includes both the key & value. + */ ++ (NSMutableCharacterSet *)URLParamValueAllowedCharacters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.m new file mode 100644 index 00000000..07050c90 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLQueryComponent.m @@ -0,0 +1,219 @@ +/*! @file OIDURLQueryComponent.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDURLQueryComponent.h" + +BOOL gOIDURLQueryComponentForceIOS7Handling = NO; + +/*! @brief String representing the set of characters that are valid for the URL query + (per @ NSCharacterSet.URLQueryAllowedCharacterSet), but are disallowed in URL query + parameters and values. + */ +static NSString *const kQueryStringParamAdditionalDisallowedCharacters = @"=&+"; + +@implementation OIDURLQueryComponent { + /*! @brief A dictionary of parameter names and values representing the contents of the query. + */ + NSMutableDictionary *> *_parameters; +} + +- (nullable instancetype)init { + self = [super init]; + if (self) { + _parameters = [NSMutableDictionary dictionary]; + } + return self; +} + +- (nullable instancetype)initWithURL:(NSURL *)URL { + self = [self init]; + if (self) { + if (@available(iOS 8.0, macOS 10.10, *)) { + // If NSURLQueryItem is available, use it for deconstructing the new URL. (iOS 8+) + if (!gOIDURLQueryComponentForceIOS7Handling) { + NSURLComponents *components = + [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO]; + // As OAuth uses application/x-www-form-urlencoded encoding, interprets '+' as a space + // in addition to regular percent decoding. https://url.spec.whatwg.org/#urlencoded-parsing + components.percentEncodedQuery = + [components.percentEncodedQuery stringByReplacingOccurrencesOfString:@"+" + withString:@"%20"]; + // NB. @c queryItems are already percent decoded + NSArray *queryItems = components.queryItems; + for (NSURLQueryItem *queryItem in queryItems) { + [self addParameter:queryItem.name value:queryItem.value]; + } + return self; + } + } + + // Fallback for iOS 7 + NSString *query = URL.query; + // As OAuth uses application/x-www-form-urlencoded encoding, interprets '+' as a space + // in addition to regular percent decoding. https://url.spec.whatwg.org/#urlencoded-parsing + query = [query stringByReplacingOccurrencesOfString:@"+" withString:@"%20"]; + + NSArray *queryParts = [query componentsSeparatedByString:@"&"]; + for (NSString *queryPart in queryParts) { + NSRange equalsRange = [queryPart rangeOfString:@"="]; + if (equalsRange.location == NSNotFound) { + continue; + } + NSString *name = [queryPart substringToIndex:equalsRange.location]; + name = name.stringByRemovingPercentEncoding; + NSString *value = [queryPart substringFromIndex:equalsRange.location + equalsRange.length]; + value = value.stringByRemovingPercentEncoding; + [self addParameter:name value:value]; + } + return self; + } + return self; +} + +- (NSArray *)parameters { + return _parameters.allKeys; +} + +- (NSDictionary *> *)dictionaryValue { + // This method will flatten arrays in our @c _parameters' values if only one value exists. + NSMutableDictionary *> *values = [NSMutableDictionary dictionary]; + for (NSString *parameter in _parameters.allKeys) { + NSArray *value = _parameters[parameter]; + if (value.count == 1) { + values[parameter] = [value.firstObject copy]; + } else { + values[parameter] = [value copy]; + } + } + return values; +} + +- (NSArray *)valuesForParameter:(NSString *)parameter { + return _parameters[parameter]; +} + +- (void)addParameter:(NSString *)parameter value:(NSString *)value { + NSMutableArray *parameterValues = _parameters[parameter]; + if (!parameterValues) { + parameterValues = [NSMutableArray array]; + _parameters[parameter] = parameterValues; + } + [parameterValues addObject:value]; +} + +- (void)addParameters:(NSDictionary *)parameters { + for (NSString *parameterName in parameters.allKeys) { + [self addParameter:parameterName value:parameters[parameterName]]; + } +} + +/*! @brief Builds a query items array that can be set to @c NSURLComponents.queryItems + @discussion The parameter names and values are NOT URL encoded. + @return An array of unencoded @c NSURLQueryItem objects. + */ +- (NSMutableArray *)queryItems NS_AVAILABLE(10.10, 8.0) { + NSMutableArray *queryParameters = [NSMutableArray array]; + for (NSString *parameterName in _parameters.allKeys) { + NSArray *values = _parameters[parameterName]; + for (NSString *value in values) { + NSURLQueryItem *item = [NSURLQueryItem queryItemWithName:parameterName value:value]; + [queryParameters addObject:item]; + } + } + return queryParameters; +} + ++ (NSMutableCharacterSet *)URLParamValueAllowedCharacters { + // Starts with the standard URL-allowed character set. + NSMutableCharacterSet *allowedParamCharacters = + [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + // Removes additional characters we don't want to see in the query component. + [allowedParamCharacters removeCharactersInString:kQueryStringParamAdditionalDisallowedCharacters]; + return allowedParamCharacters; +} + +/*! @brief Builds a query string that can be set to @c NSURLComponents.percentEncodedQuery + @discussion This string is percent encoded, and shouldn't be used with + @c NSURLComponents.query. + @return An percentage encoded query string. + */ +- (NSString *)percentEncodedQueryString { + NSMutableArray *parameterizedValues = [NSMutableArray array]; + + // Starts with the standard URL-allowed character set. + NSMutableCharacterSet *allowedParamCharacters = [[self class] URLParamValueAllowedCharacters]; + + for (NSString *parameterName in _parameters.allKeys) { + NSString *encodedParameterName = + [parameterName stringByAddingPercentEncodingWithAllowedCharacters:allowedParamCharacters]; + + NSArray *values = _parameters[parameterName]; + for (NSString *value in values) { + NSString *encodedValue = + [value stringByAddingPercentEncodingWithAllowedCharacters:allowedParamCharacters]; + NSString *parameterizedValue = + [NSString stringWithFormat:@"%@=%@", encodedParameterName, encodedValue]; + [parameterizedValues addObject:parameterizedValue]; + } + } + + NSString *queryString = [parameterizedValues componentsJoinedByString:@"&"]; + return queryString; +} + +- (NSString *)URLEncodedParameters { + // If NSURLQueryItem is available, uses it for constructing the encoded parameters. (iOS 8+) + if (@available(iOS 8.0, macOS 10.10, *)) { + if (!gOIDURLQueryComponentForceIOS7Handling) { + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = [self queryItems]; + NSString *encodedQuery = components.percentEncodedQuery; + // NSURLComponents.percentEncodedQuery creates a validly escaped URL query component, but + // doesn't encode the '+' leading to potential ambiguity with application/x-www-form-urlencoded + // encoding. Percent encodes '+' to avoid this ambiguity. + encodedQuery = [encodedQuery stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"]; + return encodedQuery; + } + } + + // else, falls back to building query string manually (iOS 7) + return [self percentEncodedQueryString]; +} + +- (NSURL *)URLByReplacingQueryInURL:(NSURL *)URL { + NSURLComponents *components = + [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO]; + + // Replaces encodedQuery component + NSString *queryString = [self URLEncodedParameters]; + components.percentEncodedQuery = queryString; + + NSURL *URLWithParameters = components.URL; + return URLWithParameters; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, parameters: %@>", + NSStringFromClass([self class]), + (void *)self, + _parameters]; +} + +@end diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.h b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.h new file mode 100644 index 00000000..28e91169 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.h @@ -0,0 +1,40 @@ +/*! @file OIDURLSessionProvider.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief A NSURLSession provider that allows clients to provide custom implementation + for NSURLSession + */ +@interface OIDURLSessionProvider : NSObject + +/*! @brief Obtains the current @c NSURLSession; using the +[NSURLSession sharedSession] if + no custom implementation is provided. + @return NSURLSession object to be used for making network requests. + */ ++ (NSURLSession *)session; + +/*! @brief Allows library consumers to change the @c NSURLSession instance used to make + network requests. + @param session The @c NSURLSession instance that should be used for making network requests. + */ ++ (void)setSession:(NSURLSession *)session; +@end +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.m b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.m new file mode 100644 index 00000000..fca17fe7 --- /dev/null +++ b/MyExperiences copy/Pods/AppAuth/Source/AppAuthCore/OIDURLSessionProvider.m @@ -0,0 +1,39 @@ +/*! @file OIDURLSessionProvider.m + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "OIDURLSessionProvider.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSURLSession *__nullable gURLSession; + +@implementation OIDURLSessionProvider + ++ (NSURLSession *)session { + if (!gURLSession) { + gURLSession = [NSURLSession sharedSession]; + } + return gURLSession; +} + ++ (void)setSession:(NSURLSession *)session { + NSAssert(session, @"Parameter: |session| must be non-nil."); + gURLSession = session; +} +@end +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/Firebase.h b/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/Firebase.h new file mode 100755 index 00000000..e5049ca4 --- /dev/null +++ b/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/Firebase.h @@ -0,0 +1,172 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#if !defined(__has_include) + #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \ + import the headers individually." +#else + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Dynamic Links works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase In App Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif +#endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Performance works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Remote Config works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + +#endif // defined(__has_include) diff --git a/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/module.modulemap b/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/module.modulemap new file mode 100755 index 00000000..3685b54a --- /dev/null +++ b/MyExperiences copy/Pods/Firebase/CoreOnly/Sources/module.modulemap @@ -0,0 +1,4 @@ +module Firebase { + export * + header "Firebase.h" +} \ No newline at end of file diff --git a/MyExperiences copy/Pods/Firebase/LICENSE b/MyExperiences copy/Pods/Firebase/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/Firebase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/Firebase/README.md b/MyExperiences copy/Pods/Firebase/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/Firebase/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector new file mode 100755 index 00000000..dd943818 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap new file mode 100755 index 00000000..99a4b1dc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module FIRAnalyticsConnector { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics new file mode 100755 index 00000000..656fb342 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h new file mode 100755 index 00000000..d499af66 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h @@ -0,0 +1,62 @@ +#import + +#import "FIRAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides App Delegate handlers to be used in your App Delegate. + * + * To save time integrating Firebase Analytics in an application, Firebase Analytics does not + * require delegation implementation from the AppDelegate. Instead this is automatically done by + * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App + * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting + * it to NO, and adding the methods in this category to corresponding delegation handlers. + * + * To handle Universal Links, you must return YES in + * [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. + */ +@interface FIRAnalytics (AppDelegate) + +/** + * Handles events related to a URL session that are waiting to be processed. + * + * For optimal use of Firebase Analytics, call this method from the + * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler] + * method of the app delegate in your app. + * + * @param identifier The identifier of the URL session requiring attention. + * @param completionHandler The completion handler to call when you finish processing the events. + * Calling this completion handler lets the system know that your app's user interface is + * updated and a new snapshot can be taken. + */ ++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(nullable void (^)(void))completionHandler; + +/** + * Handles the event when the app is launched by a URL. + * + * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and + * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on + * iOS 8.x and below) in your app. + * + * @param url The URL resource to open. This resource can be a network resource or a file. + */ ++ (void)handleOpenURL:(NSURL *)url; + +/** + * Handles the event when the app receives data associated with user activity that includes a + * Universal Link (on iOS 9.0 and above). + * + * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app + * delegate (on iOS 9.0 and above). + * + * @param userActivity The activity object containing the data associated with the task the user + * was performing. + */ ++ (void)handleUserActivity:(id)userActivity; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h new file mode 100755 index 00000000..be0b1fae --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -0,0 +1,136 @@ +#import + +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" + +NS_ASSUME_NONNULL_BEGIN + +/// The top level Firebase Analytics singleton that provides methods for logging events and setting +/// user properties. See the developer guides for general +/// information on using Firebase Analytics in your apps. +/// +/// @note The Analytics SDK uses SQLite to persist events and other app-specific data. Calling +/// certain thread-unsafe global SQLite methods like `sqlite3_shutdown()` can result in +/// unexpected crashes at runtime. +NS_SWIFT_NAME(Analytics) +@interface FIRAnalytics : NSObject + +/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have +/// the same parameters. Up to 500 event names are supported. Using predefined events and/or +/// parameters is recommended for optimal reporting. +/// +/// The following event names are reserved and cannot be used: +///
    +///
  • ad_activeview
  • +///
  • ad_click
  • +///
  • ad_exposure
  • +///
  • ad_impression
  • +///
  • ad_query
  • +///
  • adunit_exposure
  • +///
  • app_clear_data
  • +///
  • app_remove
  • +///
  • app_update
  • +///
  • error
  • +///
  • first_open
  • +///
  • in_app_purchase
  • +///
  • notification_dismiss
  • +///
  • notification_foreground
  • +///
  • notification_open
  • +///
  • notification_receive
  • +///
  • os_update
  • +///
  • screen_view
  • +///
  • session_start
  • +///
  • user_engagement
  • +///
+/// +/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or +/// underscores. The name must start with an alphabetic character. Some event names are +/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are +/// case-sensitive and that logging two events whose names differ only in case will result in +/// two distinct events. +/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has +/// no parameters. Parameter names can be up to 40 characters long and must start with an +/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString +/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are +/// supported. NSString parameter values can be up to 100 characters long. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names. ++ (void)logEventWithName:(NSString *)name + parameters:(nullable NSDictionary *)parameters + NS_SWIFT_NAME(logEvent(_:parameters:)); + +/// Sets a user property to a given value. Up to 25 user property names are supported. Once set, +/// user property values persist throughout the app lifecycle and across sessions. +/// +/// The following user property names are reserved and cannot be used: +///
    +///
  • first_open_time
  • +///
  • last_deep_link_referrer
  • +///
  • user_id
  • +///
+/// +/// @param value The value of the user property. Values can be up to 36 characters long. Setting the +/// value to nil removes the user property. +/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters +/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and +/// "ga_" prefixes are reserved and should not be used for user property names. ++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name + NS_SWIFT_NAME(setUserProperty(_:forName:)); + +/// Sets the user ID property. This feature must be used in accordance with +/// Google's Privacy Policy +/// +/// @param userID The user ID to ascribe to the user of this app on this device, which must be +/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID. ++ (void)setUserID:(nullable NSString *)userID; + +/// Sets the current screen name, which specifies the current visual context in your app. This helps +/// identify the areas in your app where users spend their time and how they interact with your app. +/// Must be called on the main thread. +/// +/// Note that screen reporting is enabled automatically and records the class name of the current +/// UIViewController for you without requiring you to call this method. If you implement +/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class +/// will not be automatically tracked. The class name can optionally be overridden by calling this +/// method in the viewDidAppear callback of your UIViewController and specifying the +/// screenClassOverride parameter. setScreenName:screenClass: must be called after +/// [super viewDidAppear:]. +/// +/// If your app does not use a distinct UIViewController for each screen, you should call this +/// method and specify a distinct screenName each time a new screen is presented to the user. +/// +/// The screen name and screen class remain in effect until the current UIViewController changes or +/// a new call to setScreenName:screenClass: is made. +/// +/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil +/// to clear the current screen name. +/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By +/// default this is the class name of the current UIViewController. Set to nil to revert to the +/// default class name. ++ (void)setScreenName:(nullable NSString *)screenName + screenClass:(nullable NSString *)screenClassOverride; + +/// Sets whether analytics collection is enabled for this app on this device. This setting is +/// persisted across app sessions. By default it is enabled. +/// +/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection. ++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets the interval of inactivity in seconds that terminates the current session. The default +/// value is 1800 seconds (30 minutes). +/// +/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current +/// session terminates. ++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval; + +/// The unique ID for this instance of the application. ++ (NSString *)appInstanceID; + +/// Clears all analytics data for this instance from the device and resets the app instance ID. +/// FIRAnalyticsConfiguration values will be reset to the default values. ++ (void)resetAnalyticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h new file mode 100755 index 00000000..807b6159 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -0,0 +1,471 @@ +/// @file FIREventNames.h +/// +/// Predefined event names. +/// +/// An Event is an important occurrence in your app that you want to measure. You can report up to +/// 500 different types of Events per app and you can associate up to 25 unique parameters with each +/// Event type. Some common events are suggested below, but you may also choose to specify custom +/// Event types that are associated with your specific app. Each event type is identified by a +/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. + +#import + +/// Add Payment Info event. This event signifies that a user has submitted their payment +/// information. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterPaymentType (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) = + @"add_payment_info"; + +/// E-Commerce Add To Cart event. This event signifies that an item(s) was added to a cart for +/// purchase. Add this event to a funnel with @c kFIREventPurchase to gauge the effectiveness of +/// your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart"; + +/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. Use +/// this event to identify popular gift items. Note: If you supply the @c kFIRParameterValue +/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue metrics +/// can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) = + @"add_to_wishlist"; + +/// App Open event. By logging this event when an App becomes active, developers can understand how +/// often users leave and return during the course of a Session. Although Sessions are automatically +/// reported, this event can provide further clarification around the continuous engagement of +/// app-users. +static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open"; + +/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of +/// checking out. Add this event to a funnel with your @c kFIREventPurchase event to gauge the +/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, +/// you must also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be +/// computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) = + @"begin_checkout"; + +/// Campaign Detail event. Log this event to supply the referral details of a re-engagement +/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource, +/// kFIRParameterMedium or kFIRParameterCampaign. Params: +/// +///
    +///
  • @c kFIRParameterSource (NSString)
  • +///
  • @c kFIRParameterMedium (NSString)
  • +///
  • @c kFIRParameterCampaign (NSString)
  • +///
  • @c kFIRParameterTerm (NSString) (optional)
  • +///
  • @c kFIRParameterContent (NSString) (optional)
  • +///
  • @c kFIRParameterAdNetworkClickID (NSString) (optional)
  • +///
  • @c kFIRParameterCP1 (NSString) (optional)
  • +///
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) = + @"campaign_details"; + +/// Checkout progress. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString) (optional)
  • +///
+/// This constant has been deprecated. +static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) = + @"checkout_progress"; + +/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log +/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy. +/// Params: +/// +///
    +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventEarnVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency"; + +/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterLocation (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+/// This constant has been deprecated. Use @c kFIREventPurchase constant instead. +static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) = + @"ecommerce_purchase"; + +/// Generate Lead event. Log this event when a lead has been generated in the app to understand the +/// efficacy of your install and re-engagement campaigns. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) = + @"generate_lead"; + +/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use +/// this event to analyze how popular certain groups or social features are in your app. Params: +/// +///
    +///
  • @c kFIRParameterGroupID (NSString)
  • +///
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group"; + +/// Level End event. Log this event when the user finishes a level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
  • @c kFIRParameterSuccess (NSString)
  • +///
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end"; + +/// Level Start event. Log this event when the user starts a new level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = @"level_start"; + +/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can +/// help you gauge the level distribution of your userbase and help you identify certain levels that +/// are difficult to pass. Params: +/// +///
    +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up"; + +/// Login event. Apps with a login feature can report this event to signify that a user has logged +/// in. +static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login"; + +/// Post Score event. Log this event when the user posts a score in your gaming app. This event can +/// help you understand how users are actually performing in your game and it can help you correlate +/// high scores with certain audiences or behaviors. Params: +/// +///
    +///
  • @c kFIRParameterScore (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score"; + +/// Present Offer event. This event signifies that the app has presented a purchase offer to a user. +/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge +/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+/// This constant has been deprecated. Use @c kFIREventViewPromotion constant instead. +static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) = + @"present_offer"; + +/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
+/// This constant has been deprecated. Use @c kFIREventRefund constant instead. +static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) = + @"purchase_refund"; + +/// E-Commerce Remove from Cart event. This event signifies that an item(s) was removed from a cart. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the @c +/// kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) = + @"remove_from_cart"; + +/// Search event. Apps that support search features can use this event to contextualize search +/// operations by supplying the appropriate, corresponding parameters. This event can help you +/// identify the most popular content in your app. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search"; + +/// Select Content event. This general purpose event signifies that a user has selected some content +/// of a certain type in an app. The content can be any object in your app. This event can help you +/// identify popular content and categories of content in your app. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) = + @"select_content"; + +/// Set checkout option. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString)
  • +///
+/// This constant has been deprecated. +static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) = + @"set_checkout_option"; + +/// Share event. Apps with social features can log the Share event to identify the most viral +/// content. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share"; + +/// Sign Up event. This event indicates that a user has signed up for an account in your app. The +/// parameter signifies the method by which the user signed up. Use this event to understand the +/// different behaviors between logged in and logged out users. Params: +/// +///
    +///
  • @c kFIRParameterSignUpMethod (NSString)
  • +///
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up"; + +/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can +/// help you identify which virtual goods are the most popular objects of purchase. Params: +/// +///
    +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventSpendVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency"; + +/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use +/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this +/// process and move on to the full app experience. +static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) = + @"tutorial_begin"; + +/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding +/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your +/// on-boarding process. +static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) = + @"tutorial_complete"; + +/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your +/// game. Since achievements generally represent the breadth of a gaming experience, this event can +/// help you understand how many users are experiencing all that your game has to offer. Params: +/// +///
    +///
  • @c kFIRParameterAchievementID (NSString)
  • +///
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) = + @"unlock_achievement"; + +/// View Item event. This event signifies that a user has viewed an item. Use the appropriate +/// parameters to contextualize the event. Use this event to discover the most popular items viewed +/// in your app. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item"; + +/// View Item List event. Log this event when a user sees a list of items or offerings. Params: +/// +///
    +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterItemListID (NSString) (optional)
  • +///
  • @c kFIRParameterItemListName (NSString) (optional)
  • +///
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) = + @"view_item_list"; + +/// View Search Results event. Log this event when the user has been presented with the results of a +/// search. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = + @"view_search_results"; + +/// Add Shipping Info event. This event signifies that a user has submitted their shipping +/// information. Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterShippingTier (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddShippingInfo NS_SWIFT_NAME(AnalyticsEventAddShippingInfo) = + @"add_shipping_info"; + +/// E-Commerce Purchase event. This event signifies that an item(s) was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also supply +/// the @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterAffiliation (NSString) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventPurchase NS_SWIFT_NAME(AnalyticsEventPurchase) = @"purchase"; + +/// E-Commerce Refund event. This event signifies that a refund was issued. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency parameter so +/// that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterAffiliation (NSString) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventRefund NS_SWIFT_NAME(AnalyticsEventRefund) = @"refund"; + +/// Select Item event. This event signifies that an item was selected by a user from a list. Use the +/// appropriate parameters to contextualize the event. Use this event to discover the most popular +/// items selected. Params: +/// +///
    +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterItemListID (NSString) (optional)
  • +///
  • @c kFIRParameterItemListName (NSString) (optional)
  • +///
+static NSString *const kFIREventSelectItem NS_SWIFT_NAME(AnalyticsEventSelectItem) = @"select_item"; + +/// Select promotion event. This event signifies that a user has selected a promotion offer. Use the +/// appropriate parameters to contextualize the event, such as the item(s) for which the promotion +/// applies. Params: +/// +///
    +///
  • @c kFIRParameterCreativeName (NSString) (optional)
  • +///
  • @c kFIRParameterCreativeSlot (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPromotionID (NSString) (optional)
  • +///
  • @c kFIRParameterPromotionName (NSString) (optional)
  • +///
+static NSString *const kFIREventSelectPromotion NS_SWIFT_NAME(AnalyticsEventSelectPromotion) = + @"select_promotion"; + +/// E-commerce View Cart event. This event signifies that a user has viewed their cart. Use this to +/// analyze your purchase funnel. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventViewCart NS_SWIFT_NAME(AnalyticsEventViewCart) = @"view_cart"; + +/// View Promotion event. This event signifies that a promotion was shown to a user. Add this event +/// to a funnel with the @c kFIREventAddToCart and @c kFIREventPurchase to gauge your conversion +/// process. Params: +/// +///
    +///
  • @c kFIRParameterCreativeName (NSString) (optional)
  • +///
  • @c kFIRParameterCreativeSlot (NSString) (optional)
  • +///
  • @c kFIRParameterItems (NSArray) (optional)
  • +///
  • @c kFIRParameterLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPromotionID (NSString) (optional)
  • +///
  • @c kFIRParameterPromotionName (NSString) (optional)
  • +///
+static NSString *const kFIREventViewPromotion NS_SWIFT_NAME(AnalyticsEventViewPromotion) = + @"view_promotion"; diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h new file mode 100755 index 00000000..5775d866 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h @@ -0,0 +1,670 @@ +/// @file FIRParameterNames.h +/// +/// Predefined event parameter names. +/// +/// Params supply information that contextualize Events. You can associate up to 25 unique Params +/// with each Event type. Some Params are suggested below for certain common Events, but you are +/// not limited to these. You may supply extra Params for suggested Events or custom Params for +/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. Param values can +/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and +/// should not be used. + +#import + +/// Game achievement ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) = + @"achievement_id"; + +/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format. +///
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAdNetworkClickID + NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid"; + +/// A product affiliation to designate a supplying company or brick and mortar store location +/// (NSString).
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) = + @"affiliation"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Character used in game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) = + @"character"; + +/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// 
+/// This constant has been deprecated. +static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) = + @"checkout_step"; + +/// Some option on a step in an ecommerce flow (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// 
+/// This constant has been deprecated. +static NSString *const kFIRParameterCheckoutOption + NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option"; + +/// Campaign content (NSString). +static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content"; + +/// Type of content selected (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) = + @"content_type"; + +/// Coupon code used for a purchase (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"SUMMER_FUN",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon"; + +/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign. +/// Use varies by network. +///
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1"; + +/// The name of a creative used in a promotional spot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) = + @"creative_name"; + +/// The name of a creative slot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) = + @"creative_slot"; + +/// Currency of the purchase or items associated with the event, in 3-letter +/// ISO_4217 format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) = + @"currency"; + +/// Flight or Travel destination (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) = + @"destination"; + +/// The arrival date, check-out date or rental end date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date"; + +/// Flight number for travel events (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) = + @"flight_number"; + +/// Group/clan/guild ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id"; + +/// The index of the item in a list (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(5),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index"; + +/// Item brand (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) = + @"item_brand"; + +/// Item category (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"pants",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) = + @"item_category"; + +/// Item ID (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"SKU_12345",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id"; + +/// The Google Place ID (NSString) that +/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+/// This constant has been deprecated. Use @c kFIRParameterLocationID constant instead. +static NSString *const kFIRParameterItemLocationID + NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id"; + +/// Item Name (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"jeggings",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) = + @"item_name"; + +/// The list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// 
+/// This constant has been deprecated. Use @c kFIRParameterItemListName constant instead. +static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) = + @"item_list"; + +/// Item variant (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Black",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) = + @"item_variant"; + +/// Level in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level"; + +/// Location (NSString). The Google Place ID +/// that corresponds to the associated event. Alternatively, you can supply your own custom +/// Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) = + @"location"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// Number of nights staying at hotel (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfNights + NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights"; + +/// Number of passengers traveling (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfPassengers + NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers"; + +/// Number of rooms for travel events (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) = + @"number_of_rooms"; + +/// Flight or Travel origin (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin"; + +/// Purchase price (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price"; + +/// Purchase quantity (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) = + @"quantity"; + +/// Score in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score"; + +/// The search string/keywords used (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) = + @"search_term"; + +/// Shipping cost associated with a transaction (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(5.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $5.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) = + @"shipping"; + +/// Sign up method (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// 
+/// +/// This constant has been deprecated. Use Method constant instead. +static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) = + @"sign_up_method"; + +/// A particular approach used in an operation; for example, "facebook" or "email" in the context +/// of a sign_up or login event. (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method"; + +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The departure date, check-in date or rental start date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) = + @"start_date"; + +/// Tax cost associated with a transaction (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(2.43),
+///       kFIRParameterCurrency : @"USD",  // e.g. $2.43 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax"; + +/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term"; + +/// The unique identifier of a transaction (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"T12345",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) = + @"transaction_id"; + +/// Travel class (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) = + @"travel_class"; + +/// A context-specific numeric value which is accumulated automatically for each event type. This is +/// a general purpose parameter that is useful for accumulating a key metric that pertains to an +/// event. Examples include revenue, distance, time and points. Value should be specified as signed +/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events +/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be +/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is +/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the +/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid +/// currency code for conversion events will cause that +/// conversion to be omitted from reporting. +///
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value"; + +/// Name of virtual currency type (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterVirtualCurrencyName + NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name"; + +/// The name of a level in a game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) = + @"level_name"; + +/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned +/// integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success"; + +/// Indicates that the associated event should either extend the current session +/// or start a new session if no session was active when the event was logged. +/// Specify YES to extend the current session or to start a new session; any +/// other value will not extend or start a session. +///
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) = + @"extend_session"; + +/// Monetary value of discount associated with a purchase (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDiscount : @(2.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $2.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDiscount NS_SWIFT_NAME(AnalyticsParameterDiscount) = + @"discount"; + +/// Item Category (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory2 : @"pants",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory2 NS_SWIFT_NAME(AnalyticsParameterItemCategory2) = + @"item_category2"; + +/// Item Category (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory3 : @"pants",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory3 NS_SWIFT_NAME(AnalyticsParameterItemCategory3) = + @"item_category3"; + +/// Item Category (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory4 : @"pants",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory4 NS_SWIFT_NAME(AnalyticsParameterItemCategory4) = + @"item_category4"; + +/// Item Category (context-specific) (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory5 : @"pants",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory5 NS_SWIFT_NAME(AnalyticsParameterItemCategory5) = + @"item_category5"; + +/// The ID of the list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemListID : @"ABC123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemListID NS_SWIFT_NAME(AnalyticsParameterItemListID) = + @"item_list_id"; + +/// The name of the list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemListName : @"Related products",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemListName NS_SWIFT_NAME(AnalyticsParameterItemListName) = + @"item_list_name"; + +/// The list of items involved in the transaction. (NSArray). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItems : @[
+///         @{kFIRParameterItemName : @"jeggings", kFIRParameterItemCategory : @"pants"},
+///         @{kFIRParameterItemName : @"boots", kFIRParameterItemCategory : @"shoes"},
+///       ],
+///     };
+/// 
+static NSString *const kFIRParameterItems NS_SWIFT_NAME(AnalyticsParameterItems) = @"items"; + +/// The location associated with the event. Preferred to be the Google +/// Place ID that corresponds to the +/// associated item but could be overridden to a custom location ID string.(NSString).
+///     NSDictionary *params = @{
+///       kFIRParameterLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocationID NS_SWIFT_NAME(AnalyticsParameterLocationID) = + @"location_id"; + +/// The chosen method of payment (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPaymentType : @"Visa",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPaymentType NS_SWIFT_NAME(AnalyticsParameterPaymentType) = + @"payment_type"; + +/// The ID of a product promotion (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPromotionID : @"ABC123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPromotionID NS_SWIFT_NAME(AnalyticsParameterPromotionID) = + @"promotion_id"; + +/// The name of a product promotion (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPromotionName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPromotionName NS_SWIFT_NAME(AnalyticsParameterPromotionName) = + @"promotion_name"; + +/// The shipping tier (e.g. Ground, Air, Next-day) selected for delivery of the purchased item +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShippingTier : @"Ground",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShippingTier NS_SWIFT_NAME(AnalyticsParameterShippingTier) = + @"shipping_tier"; diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h new file mode 100755 index 00000000..132aef77 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h @@ -0,0 +1,29 @@ +/// @file FIRUserPropertyNames.h +/// +/// Predefined user property names. +/// +/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can +/// later analyze different behaviors of various segments of your userbase. You may supply up to 25 +/// unique UserProperties per app, and you can use the name and value of your choosing for each one. +/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and +/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to +/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not +/// be used. + +#import + +/// The method used to sign in. For example, "google", "facebook" or "twitter". +static NSString *const kFIRUserPropertySignUpMethod + NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method"; + +/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user. +/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the +/// documentation for +/// more details and information about related settings. +/// +///
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// 
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals + NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads"; diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h new file mode 100755 index 00000000..ed7588a6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h @@ -0,0 +1,5 @@ +#import "FIRAnalytics+AppDelegate.h" +#import "FIRAnalytics.h" +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" diff --git a/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap new file mode 100755 index 00000000..d7c59054 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module FirebaseAnalytics { + umbrella header "FirebaseAnalytics.h" + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/CHANGELOG.md b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/CHANGELOG.md new file mode 100644 index 00000000..7a319088 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/CHANGELOG.md @@ -0,0 +1,253 @@ +# v6.5.3 +- [changed] Remove unused mfa request field "mfa_provider" (#5397) +- [fixed] Suppress deprecation warnings when targeting iOS versions up to iOS 13. (#5437) + +# v6.5.2 +- [fixed] Handle calls to `useUserAccessGroup` soon after configure. (#4175) + +# v6.5.1 +- [changed] File structure changes. No functional change. +- [changed] Code formatting changes. + +# v6.5.0 +- [feature] Added support of Multi-factor Authentication. (#4823) + +# v6.4.1 +- [fixed] Added support of UISceneDelegate for URL redirect. (#4380) +- [fixed] Fixed rawNonce in encoder. (#4337) + +# v6.4.0 +- [feature] Added support for Sign-in with Apple. (#4183) + +# v6.3.1 +- [fixed] Removed usage of a deprecated property on iOS 13. (#4066) + +# v6.3.0 +- [added] Added methods allowing developers to link and reauthenticate with federated providers. (#3971) + +# v6.2.3 +- [fixed] Make sure the first valid auth domain is retrieved. (#3493) +- [fixed] Add assertion for Facebook generic IDP flow. (#3208) +- [fixed] Build for Catalyst. (#3549) + +# v6.2.2 +- [fixed] Fixed an issue where unlinking an email auth provider raised an incorrect error stating the account was not linked to an email auth provider. (#3405) +- [changed] Renamed internal Keychain classes. (#3473) + +# v6.2.1 +- [added] Add new client error MISSING_CLIENT_IDENTIFIER. (#3341) + +# v6.2.0 +- [feature] Expose `secret` of OAuth credential in public header. (#3089) +- [fixed] Fix a keychain issue where API key is incorrectly set. (#3239) + +# v6.1.2 +- [fixed] Fix line limits and linter warnings in public documentation. (#3139) + +# v6.1.1 +- [fixed] Fix an issue where a user can't link with email provider by email link. (#3030) + +# v6.1.0 +- [added] Add support of web.app as an auth domain. (#2959) +- [fixed] Fix an issue where the return type of `getStoredUserForAccessGroup:error:` is nonnull. (#2879) + +# v6.0.0 +- [added] Add support of single sign on. (#2684) +- [deprecated] Deprecate `reauthenticateAndRetrieveDataWithCredential:completion:`, `signInAndRetrieveDataWithCredential:completion:`, `linkAndRetrieveDataWithCredential:completion:`, `fetchProvidersForEmail:completion:`. (#2723, #2756) +- [added] Returned oauth secret token in Generic IDP sign-in for Twitter. (#2663) +- [removed] Remove pendingToken from public API. (#2676) +- [changed] `GULAppDelegateSwizzler` is used for the app delegate swizzling. (#2591) + +# v5.4.2 +- [added] Support new error code ERROR_INVALID_PROVIDER_ID. (#2629) + +# v5.4.1 +- [deprecated] Deprecate Microsoft and Yahoo OAuth Provider ID (#2517) +- [fixed] Fix an issue where an exception was thrown when linking OAuth credentials. (#2521) +- [fixed] Fix an issue where a wrong error was thrown when handling error with + FEDERATED_USER_ID_ALREADY_LINKED. (#2522) + +# v5.4.0 +- [added] Add support of Generic IDP (#2405). + +# v5.3.0 +- [changed] Use the new registerInternalLibrary API to register with FirebaseCore. (#2137) + +# v5.2.0 +- [added] Add support of Game Center sign in (#2127). + +# v5.1.0 +- [added] Add support of custom FDL domain link (#2121). + +# v5.0.5 +- [changed] Restore SafariServices framework dependency (#2002). + +# v5.0.4 +- [fixed] Fix analyzer issues (#1740). + +# v5.0.3 +- [added] Add `FIRAuthErrorCodeMalformedJWT`, which is raised on JWT token parsing. + failures during auth operations (#1436). +- [changed] Migrate to use FirebaseAuthInterop interfaces to access FirebaseAuth (#1501). + +# v5.0.2 +- [fixed] Fix an issue where JWT date timestamps weren't parsed correctly. (#1319) +- [fixed] Fix an issue where anonymous accounts weren't correctly promoted to + non-anonymous when linked with passwordless email auth accounts. (#1383) +- [fixed] Fix an exception from using an invalidated NSURLSession. (#1261) +- [fixed] Fix a data race issue caught by the sanitizer. (#1446) + +# v5.0.1 +- [fixed] Restore 4.x level of support for extensions (#1357). + +# v5.0.0 +- [added] Adds APIs for phone Auth testing to bypass the verification flow (#1192). +- [feature] Changes the callback block signature for sign in and create user methods + to provide an AuthDataResult that includes the user and user info (#1123, #1186). +- [changed] Removes GoogleToolboxForMac dependency (#1175). +- [removed] Removes miscellaneous deprecated APIs (#1188, #1200). + +# v4.6.1 +- [fixed] Fixes crash which occurred when certain Firebase IDTokens were being parsed (#1076). + +# v4.6.0 +- [added] Adds `getIDTokenResultWithCompletion:` and `getIDTokenResultForcingRefresh:completion:` APIs which + call back with an AuthTokenResult object. The Auth token result object contains the ID token JWT string and other properties associated with the token including the decoded available payload claims (#1004). + +- [added] Adds the `updateCurrentUser:completion:` API which sets the currentUser on the calling Auth instance to the provided user object (#1018). + +- [added] Adds client-side validation to prevent setting `handleCodeInApp` to false when performing + email-link authentication. If `handleCodeInApp` is set to false an invalid argument exception + is thrown (#931). + +- [added] Adds support for passing the deep link (which is embedded in the sign-in link sent via email) to the + `signInWithEmail:link:completion:` and `isSignInWithEmailLink:` methods during an + email/link sign-in flow (#1023). + +# v4.5.0 +- [added] Adds new API which provides a way to determine the sign-in methods associated with an + email address. +- [added] Adds new API which allows authentication using only an email link (Passwordless Authentication + with email link). + +# v4.4.4 +- [fixed] Addresses CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings that surface in newer versions of + Xcode and CocoaPods. +- [fixed] Improves FIRUser documentation with clear message explaining when Firebase Auth attempts to validate + users and what happens when an invalidated user is detected (#694) . + +# v4.4.3 +- [added] Adds an explicit dependency on CoreGraphics from Firebase Auth. + +# v4.4.2 +- [fixed] Fixes bug where the FIRAuthResult object returned following a Phone Number authentication + always contained a nil FIRAdditionalUserInfo object. Now the FIRAdditionalUserInfo object is + never nil and its newUser field is populated correctly. + +# v4.4.0 +- [fixed] Adds new APIs which return an AuthDataResult object after successfully creating an + Email/Password user, signing in anonymously, signing in with Email/Password and signing + in with Custom Token. The AuthDataResult object contains the new user and additional + information pertaining to the new user. + +# v4.3.2 +- [fixed] Improves error handling for the phone number sign-in reCAPTCHA flow. +- [fixed] Improves error handling for phone number linking flow. +- [fixed] Fixes issue where after linking an anonymous user to a phone number the user remained + anonymous. + +# v4.3.1 +- [changed] Internal clean up. + +# v4.3.0 +- [added] Provides account creation and last sign-in dates as metadata to the user + object. +- [added] Returns more descriptive errors for some error cases of the phone number + sign-in reCAPTCHA flow. +- [fixed] Fixes an issue that invalid users were not automatically signed out earlier. +- [fixed] Fixes an issue that ID token listeners were not fired in some cases. + +# v4.2.1 +- [fixed] Fixes a threading issue in phone number auth that completion block was not + executed on the main thread in some error cases. + +# v4.2.0 +- [added] Adds new phone number verification API which makes use of an intelligent reCAPTCHA to verify the application. + +# v4.1.1 +- [changed] Improves some method documentation in headers. + +# v4.1.0 +- [added] Allows the app to handle continue URL natively, e.g., from password reset + email. +- [added] Allows the app to set language code, e.g., for sending password reset email. +- [fixed] Fixes an issue that user's phone number did not persist on client. +- [fixed] Fixes an issue that recover email action code type was reported as unknown. +- [feature] Improves app start-up time by moving initialization off from the main + thread. +- [fixed] Better reports missing email error when creating a new password user. +- [fixed] Changes console message logging levels to be more consistent with other + Firebase products on the iOS platform. + +# 2017-05-17 -- v4.0.0 +- [added] Adds Phone Number Authentication. +- [added] Adds support for generic OAuth2 identity providers. +- [added] Adds methods that return additional user data from identity providers if + available when authenticating users. +- [added] Improves session management by automatically refreshing tokens if possible + and signing out users if the session is detected invalidated, for example, + after the user changed password or deleted account from another device. +- [fixed] Fixes an issue that reauthentication creates new user account if the user + credential is valid but does not match the currently signed in user. +- [fixed] Fixes an issue that the "password" provider is not immediately listed on the + client side after adding a password to an account. +- [changed] Changes factory methods to return non-null FIRAuth instances or raises an + exception, instead of returning nullable instances. +- [changed] Changes auth state change listener to only be triggered when the user changes. +- [added] Adds a new listener which is triggered whenever the ID token is changed. +- [changed] Switches ERROR_EMAIL_ALREADY_IN_USE to + ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL when the email used in the + signInWithCredential: call is already in use by another account. +- [deprecated] Deprecates FIREmailPasswordAuthProvider in favor of FIREmailAuthProvider. +- [deprecated] Deprecates getTokenWithCompletion in favor of getIDTokenWithCompletion on + FIRUser. +- [fixed] Changes Swift API names to better align with Swift convention. + +# 2017-02-06 -- v3.1.1 +- [added] Allows handling of additional errors when sending OOB action emails. The + server can respond with the following new error messages: + INVALID_MESSAGE_PAYLOAD,INVALID_SENDER and INVALID_RECIPIENT_EMAIL. +- [fixed] Removes incorrect reference to FIRAuthErrorCodeCredentialTooOld in FIRUser.h. +- [added] Provides additional error information from server if available. + +# 2016-12-13 -- v3.1.0 +- [added] Adds FIRAuth methods that enable the app to follow up with user actions + delivered by email, such as verifying email address or reset password. +- [fixed] No longer applies the keychain workaround introduced in v3.0.5 on iOS 10.2 + simulator or above since the issue has been fixed. +- [fixed] Fixes nullability compilation warnings when used in Swift. +- [fixed] Better reports missing password error. + +# 2016-10-24 -- v3.0.6 +- [changed] Switches to depend on open sourced GoogleToolboxForMac and GTMSessionFetcher. +- [fixed] Improves logging of keychain error when initializing. + +# 2016-09-14 -- v3.0.5 +- [fixed] Works around a keychain issue in iOS 10 simulator. +- [fixed] Reports the correct error for invalid email when signing in with email and + password. + +# 2016-07-18 -- v3.0.4 +- [fixed] Fixes a race condition bug that could crash the app with an exception from + NSURLSession on iOS 9. + +# 2016-06-20 -- v3.0.3 +- [added] Adds documentation for all possible errors returned by each method. +- [fixed] Improves error handling and messages for a variety of error conditions. +- [fixed] Whether or not an user is considered anonymous is now consistent with other + platforms. +- [changed] A saved signed in user is now siloed between different Firebase projects + within the same app. + +# 2016-05-18 -- v3.0.2 +- Initial public release. diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/README.md b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/README.md new file mode 100644 index 00000000..f6e123e3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/README.md @@ -0,0 +1,17 @@ +# Firebase Auth for iOS + +Firebase Auth enables apps to easily support multiple authentication options +for their end users. + +Please visit [our developer site](https://firebase.google.com/docs/auth/) for +integration instructions, documentation, support information, and terms of +service. + +# Firebase Auth Development + +Example/Auth contains a set of samples and tests that integrate with +FirebaseAuth. + +The unit tests run without any additional configuration along with the rest of +Firebase. See [Example/Auth/README.md](../../Example/Auth/README.md) for +information about setting up, running, and testing the samples. diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRActionCodeSettings.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRActionCodeSettings.m new file mode 100644 index 00000000..e45bb600 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRActionCodeSettings.m @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRActionCodeSettings + +- (instancetype)init { + self = [super init]; + if (self) { + _iOSBundleID = [NSBundle mainBundle].bundleIdentifier; + } + return self; +} + +- (void)setIOSBundleID:(NSString *)iOSBundleID { + _iOSBundleID = [iOSBundleID copy]; +} + +- (void)setAndroidPackageName:(NSString *)androidPackageName + installIfNotAvailable:(BOOL)installIfNotAvailable + minimumVersion:(nullable NSString *)minimumVersion { + _androidPackageName = [androidPackageName copy]; + _androidInstallIfNotAvailable = installIfNotAvailable; + _androidMinimumVersion = [minimumVersion copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth.m new file mode 100644 index 00000000..577be48d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth.m @@ -0,0 +1,2247 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" + +#if __has_include() +#import +#endif + +#import +#import +#import +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthOperationType.h" +#import "FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h" +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h" +#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h" +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h" +#import "FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h" +#import "FirebaseAuth/Sources/User/FIRUser_Internal.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h" + +#if TARGET_OS_IOS +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Constants + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName FIRAuthStateDidChangeNotification = @"FIRAuthStateDidChangeNotification"; +#else +NSString *const FIRAuthStateDidChangeNotification = @"FIRAuthStateDidChangeNotification"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** @var kMaxWaitTimeForBackoff + @brief The maximum wait time before attempting to retry auto refreshing tokens after a failed + attempt. + @remarks This is the upper limit (in seconds) of the exponential backoff used for retrying + token refresh. + */ +static NSTimeInterval kMaxWaitTimeForBackoff = 16 * 60; + +/** @var kTokenRefreshHeadStart + @brief The amount of time before the token expires that proactive refresh should be attempted. + */ +NSTimeInterval kTokenRefreshHeadStart = 5 * 60; + +/** @var kUserKey + @brief Key of user stored in the keychain. Prefixed with a Firebase app name. + */ +static NSString *const kUserKey = @"%@_firebase_user"; + +/** @var kMissingEmailInvalidParameterExceptionReason + @brief The reason for @c invalidParameterException when the email used to initiate password + reset is nil. + */ +static NSString *const kMissingEmailInvalidParameterExceptionReason = + @"The email used to initiate password reset cannot be nil."; + +/** @var kHandleCodeInAppFalseExceptionReason + @brief The reason for @c invalidParameterException when the handleCodeInApp parameter is false + on the ActionCodeSettings object used to send the link for Email-link Authentication. + */ +static NSString *const kHandleCodeInAppFalseExceptionReason = + @"You must set handleCodeInApp in your ActionCodeSettings to true for Email-link " + "Authentication."; + +static NSString *const kInvalidEmailSignInLinkExceptionMessage = + @"The link provided is not valid for email/link sign-in. Please check the link by calling " + "isSignInWithEmailLink:link: on Auth before attempting to use it for email/link sign-in."; + +/** @var kPasswordResetRequestType + @brief The action code type value for resetting password in the check action code response. + */ +static NSString *const kPasswordResetRequestType = @"PASSWORD_RESET"; + +/** @var kVerifyEmailRequestType + @brief The action code type value for verifying email in the check action code response. + */ +static NSString *const kVerifyEmailRequestType = @"VERIFY_EMAIL"; + +/** @var kRecoverEmailRequestType + @brief The action code type value for recovering email in the check action code response. + */ +static NSString *const kRecoverEmailRequestType = @"RECOVER_EMAIL"; + +/** @var kEmailLinkSignInRequestType + @brief The action code type value for an email sign-in link in the check action code response. +*/ +static NSString *const kEmailLinkSignInRequestType = @"EMAIL_SIGNIN"; + +/** @var kVerifyAndChangeEmailRequestType + @brief The action code type value for verifing and changing email in the check action code + response. + */ +static NSString *const kVerifyAndChangeEmailRequestType = @"VERIFY_AND_CHANGE_EMAIL"; + +/** @var kRevertSecondFactorAdditionRequestType + @brief The action code type value for reverting second factor addition in the check action code + response. + */ +static NSString *const kRevertSecondFactorAdditionRequestType = @"REVERT_SECOND_FACTOR_ADDITION"; + +/** @var kMissingPasswordReason + @brief The reason why the @c FIRAuthErrorCodeWeakPassword error is thrown. + @remarks This error message will be localized in the future. + */ +static NSString *const kMissingPasswordReason = @"Missing Password"; + +/** @var gKeychainServiceNameForAppName + @brief A map from Firebase app name to keychain service names. + @remarks This map is needed for looking up the keychain service name after the FIRApp instance + is deleted, to remove the associated keychain item. Accessing should occur within a + @syncronized([FIRAuth class]) context. + */ +static NSMutableDictionary *gKeychainServiceNameForAppName; + +#pragma mark - FIRActionCodeInfo + +@interface FIRActionCodeInfo () + +/** + @brief The operation being performed. + */ +@property(nonatomic, readwrite) FIRActionCodeOperation operation; + +/** @property email + @brief The email address to which the code was sent. The new email address in the case of + FIRActionCodeOperationRecoverEmail. + */ +@property(nonatomic, nullable, readwrite, copy) NSString *email; + +/** @property previousEmail + @brief The current email address in the case of FIRActionCodeOperationRecoverEmail. + */ +@property(nonatomic, nullable, readwrite, copy) NSString *previousEmail; + +#if TARGET_OS_IOS +/** @property multiFactorInfo + @brief The MultiFactorInfo object of the second factor to be reverted in case of + FIRActionCodeMultiFactorInfoKey. + */ +@property(nonatomic, nullable, readwrite) FIRMultiFactorInfo *multiFactorInfo; +#endif + +@end + +@implementation FIRActionCodeInfo + +- (NSString *)dataForKey:(FIRActionDataKey)key { + switch (key) { + case FIRActionCodeEmailKey: + return self.email; + case FIRActionCodeFromEmailKey: + return self.previousEmail; + } +} + +- (instancetype)initWithOperation:(FIRActionCodeOperation)operation + email:(NSString *)email + newEmail:(nullable NSString *)newEmail { + self = [super init]; + if (self) { + _operation = operation; + if (newEmail) { + _email = [newEmail copy]; + _previousEmail = [email copy]; + } else { + _email = [email copy]; + } + } + return self; +} + +/** @fn actionCodeOperationForRequestType: + @brief Returns the corresponding operation type per provided request type string. + @param requestType Request type returned in in the server response. + @return The corresponding FIRActionCodeOperation for the supplied request type. + */ ++ (FIRActionCodeOperation)actionCodeOperationForRequestType:(NSString *)requestType { + if ([requestType isEqualToString:kPasswordResetRequestType]) { + return FIRActionCodeOperationPasswordReset; + } + if ([requestType isEqualToString:kVerifyEmailRequestType]) { + return FIRActionCodeOperationVerifyEmail; + } + if ([requestType isEqualToString:kRecoverEmailRequestType]) { + return FIRActionCodeOperationRecoverEmail; + } + if ([requestType isEqualToString:kEmailLinkSignInRequestType]) { + return FIRActionCodeOperationEmailLink; + } + if ([requestType isEqualToString:kVerifyAndChangeEmailRequestType]) { + return FIRActionCodeOperationVerifyAndChangeEmail; + } + if ([requestType isEqualToString:kRevertSecondFactorAdditionRequestType]) { + return FIRActionCodeOperationRevertSecondFactorAddition; + } + return FIRActionCodeOperationUnknown; +} + +@end + +#pragma mark - FIRActionCodeURL + +@implementation FIRActionCodeURL + +/** @fn FIRAuthParseURL:NSString + @brief Parses an incoming URL into all available query items. + @param urlString The url to be parsed. + @return A dictionary of available query items in the target URL. + */ ++ (NSDictionary *)parseURL:(NSString *)urlString { + NSString *linkURL = [NSURLComponents componentsWithString:urlString].query; + if (!linkURL) { + return @{}; + } + NSArray *URLComponents = [linkURL componentsSeparatedByString:@"&"]; + NSMutableDictionary *queryItems = + [[NSMutableDictionary alloc] initWithCapacity:URLComponents.count]; + for (NSString *component in URLComponents) { + NSRange equalRange = [component rangeOfString:@"="]; + if (equalRange.location != NSNotFound) { + NSString *queryItemKey = + [[component substringToIndex:equalRange.location] stringByRemovingPercentEncoding]; + NSString *queryItemValue = + [[component substringFromIndex:equalRange.location + 1] stringByRemovingPercentEncoding]; + if (queryItemKey && queryItemValue) { + queryItems[queryItemKey] = queryItemValue; + } + } + } + return queryItems; +} + ++ (nullable instancetype)actionCodeURLWithLink:(NSString *)link { + NSDictionary *queryItems = [FIRActionCodeURL parseURL:link]; + if (!queryItems.count) { + NSURLComponents *urlComponents = [NSURLComponents componentsWithString:link]; + queryItems = [FIRActionCodeURL parseURL:urlComponents.query]; + } + if (!queryItems.count) { + return nil; + } + NSString *APIKey = queryItems[@"apiKey"]; + NSString *actionCode = queryItems[@"oobCode"]; + NSString *continueURLString = queryItems[@"continueUrl"]; + NSString *languageCode = queryItems[@"languageCode"]; + NSString *mode = queryItems[@"mode"]; + NSString *tenantID = queryItems[@"tenantID"]; + return [[FIRActionCodeURL alloc] initWithAPIKey:APIKey + actionCode:actionCode + continueURLString:continueURLString + languageCode:languageCode + mode:mode + tenantID:tenantID]; +} + +- (nullable instancetype)initWithAPIKey:(NSString *)APIKey + actionCode:(NSString *)actionCode + continueURLString:(NSString *)continueURLString + languageCode:(NSString *)languageCode + mode:(NSString *)mode + tenantID:(NSString *)tenantID { + self = [super init]; + if (self) { + _APIKey = APIKey; + _operation = [FIRActionCodeInfo actionCodeOperationForRequestType:mode]; + _code = actionCode; + _continueURL = [NSURL URLWithString:continueURLString]; + _languageCode = languageCode; + } + return self; +} + +@end + +#pragma mark - FIRAuth + +#if TARGET_OS_IOS +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 +@interface FIRAuth () +#else +@interface FIRAuth () +#endif +#else +@interface FIRAuth () +#endif + +/** @property firebaseAppId + @brief The Firebase app ID. + */ +@property(nonatomic, copy, readonly) NSString *firebaseAppId; + +/** @property additionalFrameworkMarker + @brief Additional framework marker that will be added as part of the header of every request. + */ +@property(nonatomic, copy, nullable) NSString *additionalFrameworkMarker; + +/** @property storedUserManager + @brief The stored user manager. + */ +@property(nonatomic, strong, nullable) FIRAuthStoredUserManager *storedUserManager; + +/** @fn initWithApp: + @brief Creates a @c FIRAuth instance associated with the provided @c FIRApp instance. + @param app The application to associate the auth instance with. + */ +- (instancetype)initWithApp:(FIRApp *)app; + +@end + +@implementation FIRAuth { + /** @var _currentUser + @brief The current user. + */ + FIRUser *_currentUser; + + /** @var _firebaseAppName + @brief The Firebase app name. + */ + NSString *_firebaseAppName; + + /** @var _listenerHandles + @brief Handles returned from @c NSNotificationCenter for blocks which are "auth state did + change" notification listeners. + @remarks Mutations should occur within a @syncronized(self) context. + */ + NSMutableArray *_listenerHandles; + + /** @var _keychainServices + @brief The keychain service. + */ + FIRAuthKeychainServices *_keychainServices; + + /** @var _lastNotifiedUserToken + @brief The user access (ID) token used last time for posting auth state changed notification. + */ + NSString *_lastNotifiedUserToken; + + /** @var _autoRefreshTokens + @brief This flag denotes whether or not tokens should be automatically refreshed. + @remarks Will only be set to @YES if the another Firebase service is included (additionally to + Firebase Auth). + */ + BOOL _autoRefreshTokens; + + /** @var _autoRefreshScheduled + @brief Whether or not token auto-refresh is currently scheduled. + */ + BOOL _autoRefreshScheduled; + + /** @var _isAppInBackground + @brief A flag that is set to YES if the app is put in the background and no when the app is + returned to the foreground. + */ + BOOL _isAppInBackground; + + /** @var _applicationDidBecomeActiveObserver + @brief An opaque object to act as the observer for UIApplicationDidBecomeActiveNotification. + */ + id _applicationDidBecomeActiveObserver; + + /** @var _applicationDidBecomeActiveObserver + @brief An opaque object to act as the observer for + UIApplicationDidEnterBackgroundNotification. + */ + id _applicationDidEnterBackgroundObserver; +} + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-auth" + withVersion:[NSString stringWithUTF8String:FirebaseAuthVersionStr]]; +} + ++ (void)initialize { + gKeychainServiceNameForAppName = [[NSMutableDictionary alloc] init]; +} + ++ (FIRAuth *)auth { + FIRApp *defaultApp = [FIRApp defaultApp]; + if (!defaultApp) { + [NSException raise:NSInternalInconsistencyException + format:@"The default FIRApp instance must be configured before the default FIRAuth" + @"instance can be initialized. One way to ensure that is to call " + @"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) in the App " + @"Delegate's `application:didFinishLaunchingWithOptions:` " + @"(`application(_:didFinishLaunchingWithOptions:)` in Swift)."]; + } + return [self authWithApp:defaultApp]; +} + ++ (FIRAuth *)authWithApp:(FIRApp *)app { + // Get the instance of Auth from the container, which will create or return the cached instance + // associated with this app. + id auth = FIR_COMPONENT(FIRAuthInterop, app.container); + return (FIRAuth *)auth; +} + +- (instancetype)initWithApp:(FIRApp *)app { + [FIRAuth setKeychainServiceNameForApp:app]; + self = [self initWithAPIKey:app.options.APIKey appName:app.name]; + if (self) { + _app = app; +#if TARGET_OS_IOS + _authURLPresenter = [[FIRAuthURLPresenter alloc] init]; +#endif + } + return self; +} + +- (nullable instancetype)initWithAPIKey:(NSString *)APIKey appName:(NSString *)appName { + self = [super init]; + if (self) { + _listenerHandles = [NSMutableArray array]; + _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:APIKey]; + _firebaseAppName = [appName copy]; +#if TARGET_OS_IOS + _settings = [[FIRAuthSettings alloc] init]; + static Class applicationClass = nil; + // iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication + // responds to it. + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + UIApplication *application = [applicationClass sharedApplication]; + + [GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods]; + [GULSceneDelegateSwizzler proxyOriginalSceneDelegate]; +#endif // TARGET_OS_IOS + + // Continue with the rest of initialization in the work thread. + __weak FIRAuth *weakSelf = self; + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + // Load current user from Keychain. + FIRAuth *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + NSString *keychainServiceName = + [FIRAuth keychainServiceNameForAppName:strongSelf->_firebaseAppName]; + if (keychainServiceName) { + strongSelf->_keychainServices = + [[FIRAuthKeychainServices alloc] initWithService:keychainServiceName]; + strongSelf.storedUserManager = + [[FIRAuthStoredUserManager alloc] initWithServiceName:keychainServiceName]; + } + + NSError *error; + NSString *storedUserAccessGroup = + [strongSelf.storedUserManager getStoredUserAccessGroupWithError:&error]; + if (!error) { + if (!storedUserAccessGroup) { + FIRUser *user; + if ([strongSelf getUser:&user error:&error]) { + [strongSelf updateCurrentUser:user byForce:NO savingToDisk:NO error:&error]; + self->_lastNotifiedUserToken = user.rawAccessToken; + } else { + FIRLogError(kFIRLoggerAuth, @"I-AUT000001", + @"Error loading saved user when starting up: %@", error); + } + } else { + [strongSelf internalUseUserAccessGroup:storedUserAccessGroup error:&error]; + if (error) { + FIRLogError(kFIRLoggerAuth, @"I-AUT000001", + @"Error loading saved user when starting up: %@", error); + } + } + } else { + FIRLogError(kFIRLoggerAuth, @"I-AUT000001", + @"Error loading saved user when starting up: %@", error); + } + +#if TARGET_OS_IOS + // Initialize for phone number auth. + strongSelf->_tokenManager = [[FIRAuthAPNSTokenManager alloc] initWithApplication:application]; + + strongSelf->_appCredentialManager = + [[FIRAuthAppCredentialManager alloc] initWithKeychain:strongSelf->_keychainServices]; + + strongSelf->_notificationManager = [[FIRAuthNotificationManager alloc] + initWithApplication:application + appCredentialManager:strongSelf->_appCredentialManager]; + + [GULAppDelegateSwizzler registerAppDelegateInterceptor:strongSelf]; +#if ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000)) + if (@available(iOS 13, tvos 13, *)) { + [GULSceneDelegateSwizzler registerSceneDelegateInterceptor:strongSelf]; + } +#endif // ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000)) +#endif // TARGET_OS_IOS + }); + } + return self; +} + +- (void)dealloc { + @synchronized(self) { + NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; + while (_listenerHandles.count != 0) { + FIRAuthStateDidChangeListenerHandle handleToRemove = _listenerHandles.lastObject; + [defaultCenter removeObserver:handleToRemove]; + [_listenerHandles removeLastObject]; + } + +#if TARGET_OS_IOS + [defaultCenter removeObserver:_applicationDidBecomeActiveObserver + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [defaultCenter removeObserver:_applicationDidEnterBackgroundObserver + name:UIApplicationDidEnterBackgroundNotification + object:nil]; +#endif + } +} + +#pragma mark - Public API + +- (nullable FIRUser *)currentUser { + __block FIRUser *result; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = self->_currentUser; + }); + return result; +} + +- (void)fetchProvidersForEmail:(NSString *)email + completion:(nullable FIRProviderQueryCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRCreateAuthURIRequest *request = + [[FIRCreateAuthURIRequest alloc] initWithIdentifier:email + continueURI:@"http://www.google.com/" + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend + createAuthURI:request + callback:^(FIRCreateAuthURIResponse *_Nullable response, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(response.allProviders, error); + }); + } + }]; + }); +} + +- (void)signInWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion { +#if TARGET_OS_IOS + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + [provider getCredentialWithUIDelegate:UIDelegate + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + if (error) { + decoratedCallback(nil, error); + return; + } + [self + internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:NO + callback:decoratedCallback]; + }]; + }); +#endif // TARGET_OS_IOS +} + +- (void)fetchSignInMethodsForEmail:(nonnull NSString *)email + completion:(nullable FIRSignInMethodQueryCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRCreateAuthURIRequest *request = + [[FIRCreateAuthURIRequest alloc] initWithIdentifier:email + continueURI:@"http://www.google.com/" + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend + createAuthURI:request + callback:^(FIRCreateAuthURIResponse *_Nullable response, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(response.signinMethods, error); + }); + } + }]; + }); +} + +- (void)signInWithEmail:(NSString *)email + password:(NSString *)password + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + [self internalSignInAndRetrieveDataWithEmail:email + password:password + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + decoratedCallback(authResult, error); + }]; + }); +} + +- (void)signInWithEmail:(NSString *)email + link:(NSString *)link + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + FIREmailPasswordAuthCredential *credential = + [[FIREmailPasswordAuthCredential alloc] initWithEmail:email link:link]; + [self internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:NO + callback:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + decoratedCallback(authResult, error); + }]; + }); +} + +/** @fn signInWithEmail:password:callback: + @brief Signs in using an email address and password. + @param email The user's email address. + @param password The user's password. + @param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked + asynchronously on the global auth work queue in the future. + @remarks This is the internal counterpart of this method, which uses a callback that does not + update the current user. + */ +- (void)signInWithEmail:(NSString *)email + password:(NSString *)password + callback:(FIRAuthResultCallback)callback { + FIRVerifyPasswordRequest *request = + [[FIRVerifyPasswordRequest alloc] initWithEmail:email + password:password + requestConfiguration:_requestConfiguration]; + + if (![request.password length]) { + callback(nil, [FIRAuthErrorUtils wrongPasswordErrorWithMessage:nil]); + return; + } + [FIRAuthBackend + verifyPassword:request + callback:^(FIRVerifyPasswordResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + callback(nil, error); + return; + } + [self completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:callback]; + }]; +} + +/** @fn internalSignInAndRetrieveDataWithEmail:password:callback: + @brief Signs in using an email address and password. + @param email The user's email address. + @param password The user's password. + @param completion A block which is invoked when the sign in finishes (or is cancelled.) Invoked + asynchronously on the global auth work queue in the future. + @remarks This is the internal counterpart of this method, which uses a callback that does not + update the current user. + */ +- (void)internalSignInAndRetrieveDataWithEmail:(NSString *)email + password:(NSString *)password + completion:(FIRAuthDataResultCallback)completion { + FIREmailPasswordAuthCredential *credentail = + [[FIREmailPasswordAuthCredential alloc] initWithEmail:email password:password]; + [self internalSignInAndRetrieveDataWithCredential:credentail + isReauthentication:NO + callback:completion]; +} + +/** @fn signInAndRetrieveDataWithGameCenterCredential:callback: + @brief Signs in using a game center credential. + @param credential The Game Center Auth Credential used to sign in. + @param callback A block which is invoked when the sign in finished (or is cancelled). Invoked + asynchronously on the global auth work queue in the future. + */ +- (void)signInAndRetrieveDataWithGameCenterCredential:(FIRGameCenterAuthCredential *)credential + callback:(FIRAuthDataResultCallback)callback { + FIRSignInWithGameCenterRequest *request = + [[FIRSignInWithGameCenterRequest alloc] initWithPlayerID:credential.playerID + publicKeyURL:credential.publicKeyURL + signature:credential.signature + salt:credential.salt + timestamp:credential.timestamp + displayName:credential.displayName + requestConfiguration:_requestConfiguration]; + [FIRAuthBackend + signInWithGameCenter:request + callback:^(FIRSignInWithGameCenterResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (callback) { + callback(nil, error); + } + return; + } + + [self + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (error && callback) { + callback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] + initWithProviderID: + FIRGameCenterAuthProviderID + profile:nil + username:nil + isNewUser:response.isNewUser]; + FIRAuthDataResult *result = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:additionalUserInfo] + : nil; + if (callback) { + callback(result, error); + } + }]; + }]; +} + +/** @fn internalSignInAndRetrieveDataWithEmail:link:completion: + @brief Signs in using an email and email sign-in link. + @param email The user's email address. + @param link The email sign-in link. + @param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked + asynchronously on the global auth work queue in the future. + */ +- (void)internalSignInAndRetrieveDataWithEmail:(nonnull NSString *)email + link:(nonnull NSString *)link + callback:(nullable FIRAuthDataResultCallback)callback { + if (![self isSignInWithEmailLink:link]) { + [FIRAuthExceptionUtils + raiseInvalidParameterExceptionWithReason:kInvalidEmailSignInLinkExceptionMessage]; + return; + } + NSDictionary *queryItems = [FIRAuthWebUtils parseURL:link]; + if (![queryItems count]) { + NSURLComponents *urlComponents = [NSURLComponents componentsWithString:link]; + queryItems = [FIRAuthWebUtils parseURL:urlComponents.query]; + } + NSString *actionCode = queryItems[@"oobCode"]; + + FIREmailLinkSignInRequest *request = + [[FIREmailLinkSignInRequest alloc] initWithEmail:email + oobCode:actionCode + requestConfiguration:_requestConfiguration]; + + [FIRAuthBackend + emailLinkSignin:request + callback:^(FIREmailLinkSignInResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + if (callback) { + callback(nil, error); + } + return; + } + [self completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (error && callback) { + callback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] + initWithProviderID:FIREmailAuthProviderID + profile:nil + username:nil + isNewUser:response.isNewUser]; + FIRAuthDataResult *result = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:additionalUserInfo] + : nil; + if (callback) { + callback(result, error); + } + }]; + }]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (void)signInWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + [self signInAndRetrieveDataWithCredential:credential completion:completion]; +} +#pragma clang diagnostic pop + +- (void)signInAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback callback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + [self internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:NO + callback:callback]; + }); +} + +- (void)internalSignInWithCredential:(FIRAuthCredential *)credential + callback:(FIRAuthResultCallback)callback { + [self internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:NO + callback:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + callback(authResult.user, error); + }]; +} + +- (void)internalSignInAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + isReauthentication:(BOOL)isReauthentication + callback:(nullable FIRAuthDataResultCallback)callback { + if ([credential isKindOfClass:[FIREmailPasswordAuthCredential class]]) { + // Special case for email/password credentials + FIREmailPasswordAuthCredential *emailPasswordCredential = + (FIREmailPasswordAuthCredential *)credential; + + if (emailPasswordCredential.link) { + // Email link sign in + [self internalSignInAndRetrieveDataWithEmail:emailPasswordCredential.email + link:emailPasswordCredential.link + callback:callback]; + } else { + // Email password sign in + FIRAuthResultCallback completeEmailSignIn = + ^(FIRUser *_Nullable user, NSError *_Nullable error) { + if (callback) { + if (error) { + callback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] initWithProviderID:FIREmailAuthProviderID + profile:nil + username:nil + isNewUser:NO]; + FIRAuthDataResult *result = + user ? [[FIRAuthDataResult alloc] initWithUser:user + additionalUserInfo:additionalUserInfo] + : nil; + callback(result, error); + } + }; + + [self signInWithEmail:emailPasswordCredential.email + password:emailPasswordCredential.password + callback:completeEmailSignIn]; + } + return; + } + + if ([credential isKindOfClass:[FIRGameCenterAuthCredential class]]) { + // Special case for Game Center credentials. + [self signInAndRetrieveDataWithGameCenterCredential:(FIRGameCenterAuthCredential *)credential + callback:callback]; + return; + } + +#if TARGET_OS_IOS + if ([credential isKindOfClass:[FIRPhoneAuthCredential class]]) { + // Special case for phone auth credentials + FIRPhoneAuthCredential *phoneCredential = (FIRPhoneAuthCredential *)credential; + FIRAuthOperationType operation = + isReauthentication ? FIRAuthOperationTypeReauth : FIRAuthOperationTypeSignUpOrSignIn; + [self + signInWithPhoneCredential:phoneCredential + operation:operation + callback:^(FIRVerifyPhoneNumberResponse *_Nullable response, + NSError *_Nullable error) { + if (callback) { + if (error) { + callback(nil, error); + return; + } + + [self + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (error && callback) { + callback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] + initWithProviderID: + FIRPhoneAuthProviderID + profile:nil + username:nil + isNewUser:response + .isNewUser]; + FIRAuthDataResult *result = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo: + additionalUserInfo] + : nil; + if (callback) { + callback(result, error); + } + }]; + } + }]; + return; + } +#endif + FIRVerifyAssertionRequest *request = + [[FIRVerifyAssertionRequest alloc] initWithProviderID:credential.provider + requestConfiguration:_requestConfiguration]; + request.autoCreate = !isReauthentication; + [credential prepareVerifyAssertionRequest:request]; + [FIRAuthBackend + verifyAssertion:request + callback:^(FIRVerifyAssertionResponse *response, NSError *error) { + if (error) { + if (callback) { + callback(nil, error); + } + return; + } + + if (response.needConfirmation) { + if (callback) { + NSString *email = response.email; + FIROAuthCredential *credential = + [[FIROAuthCredential alloc] initWithVerifyAssertionResponse:response]; + callback(nil, + [FIRAuthErrorUtils + accountExistsWithDifferentCredentialErrorWithEmail:email + updatedCredential:credential]); + } + return; + } + + if (!response.providerID.length) { + if (callback) { + callback(nil, [FIRAuthErrorUtils + unexpectedResponseWithDeserializedResponse:response]); + } + return; + } + [self + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (callback) { + if (error) { + callback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [FIRAdditionalUserInfo + userInfoWithVerifyAssertionResponse:response]; + FIROAuthCredential *updatedOAuthCredential = + [[FIROAuthCredential alloc] + initWithVerifyAssertionResponse:response]; + FIRAuthDataResult *result = + user + ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:additionalUserInfo + credential:updatedOAuthCredential] + : nil; + callback(result, error); + } + }]; + }]; +} + +- (void)signInAnonymouslyWithCompletion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + if (self->_currentUser.anonymous) { + FIRAuthDataResult *result = [[FIRAuthDataResult alloc] initWithUser:self->_currentUser + additionalUserInfo:nil]; + decoratedCallback(result, nil); + return; + } + [self internalSignInAnonymouslyWithCompletion:^(FIRSignUpNewUserResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + decoratedCallback(nil, error); + return; + } + [self completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:YES + callback:^(FIRUser *_Nullable user, NSError *_Nullable error) { + if (error) { + decoratedCallback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] initWithProviderID:nil + profile:nil + username:nil + isNewUser:YES]; + FIRAuthDataResult *authDataResult = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:additionalUserInfo] + : nil; + decoratedCallback(authDataResult, error); + }]; + }]; + }); +} + +- (void)signInWithCustomToken:(NSString *)token + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + [self internalSignInAndRetrieveDataWithCustomToken:token + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + decoratedCallback(authResult, error); + }]; + }); +} + +- (void)createUserWithEmail:(NSString *)email + password:(NSString *)password + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthDataResultCallback decoratedCallback = + [self signInFlowAuthDataResultCallbackByDecoratingCallback:completion]; + [self internalCreateUserWithEmail:email + password:password + completion:^(FIRSignUpNewUserResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + decoratedCallback(nil, error); + return; + } + [self + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (error) { + decoratedCallback(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [[FIRAdditionalUserInfo alloc] + initWithProviderID: + FIREmailAuthProviderID + profile:nil + username:nil + isNewUser:YES]; + FIRAuthDataResult *authDataResult = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo: + additionalUserInfo] + : nil; + decoratedCallback(authDataResult, error); + }]; + }]; + }); +} + +- (void)confirmPasswordResetWithCode:(NSString *)code + newPassword:(NSString *)newPassword + completion:(FIRConfirmPasswordResetCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRResetPasswordRequest *request = + [[FIRResetPasswordRequest alloc] initWithOobCode:code + newPassword:newPassword + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend + resetPassword:request + callback:^(FIRResetPasswordResponse *_Nullable response, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + completion(error); + return; + } + completion(nil); + }); + } + }]; + }); +} + +- (void)checkActionCode:(NSString *)code completion:(FIRCheckActionCodeCallBack)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRResetPasswordRequest *request = + [[FIRResetPasswordRequest alloc] initWithOobCode:code + newPassword:nil + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend + resetPassword:request + callback:^(FIRResetPasswordResponse *_Nullable response, NSError *_Nullable error) { + if (completion) { + if (error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil, error); + }); + return; + } + FIRActionCodeOperation operation = + [FIRActionCodeInfo actionCodeOperationForRequestType:response.requestType]; + FIRActionCodeInfo *actionCodeInfo = + [[FIRActionCodeInfo alloc] initWithOperation:operation + email:response.email + newEmail:response.verifiedEmail]; + dispatch_async(dispatch_get_main_queue(), ^{ + completion(actionCodeInfo, nil); + }); + } + }]; + }); +} + +- (void)verifyPasswordResetCode:(NSString *)code + completion:(FIRVerifyPasswordResetCodeCallback)completion { + [self checkActionCode:code + completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) { + if (completion) { + if (error) { + completion(nil, error); + return; + } + completion(info.email, nil); + } + }]; +} + +- (void)applyActionCode:(NSString *)code completion:(FIRApplyActionCodeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRSetAccountInfoRequest *request = + [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:self->_requestConfiguration]; + request.OOBCode = code; + [FIRAuthBackend + setAccountInfo:request + callback:^(FIRSetAccountInfoResponse *_Nullable response, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(error); + }); + } + }]; + }); +} + +- (void)sendPasswordResetWithEmail:(NSString *)email + completion:(nullable FIRSendPasswordResetCallback)completion { + [self sendPasswordResetWithNullableActionCodeSettings:nil email:email completion:completion]; +} + +- (void)sendPasswordResetWithEmail:(NSString *)email + actionCodeSettings:(FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRSendPasswordResetCallback)completion { + [self sendPasswordResetWithNullableActionCodeSettings:actionCodeSettings + email:email + completion:completion]; +} + +/** @fn sendPasswordResetWithNullableActionCodeSettings:actionCodeSetting:email:completion: + @brief Initiates a password reset for the given email address and @FIRActionCodeSettings object. + + @param actionCodeSettings Optionally, An @c FIRActionCodeSettings object containing settings + related to the handling action codes. + @param email The email address of the user. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ +- (void)sendPasswordResetWithNullableActionCodeSettings: + (nullable FIRActionCodeSettings *)actionCodeSettings + email:(NSString *)email + completion: + (nullable FIRSendPasswordResetCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + if (!email) { + [FIRAuthExceptionUtils + raiseInvalidParameterExceptionWithReason:kMissingEmailInvalidParameterExceptionReason]; + return; + } + FIRGetOOBConfirmationCodeRequest *request = [FIRGetOOBConfirmationCodeRequest + passwordResetRequestWithEmail:email + actionCodeSettings:actionCodeSettings + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend getOOBConfirmationCode:request + callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response, + NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(error); + }); + } + }]; + }); +} + +- (void)sendSignInLinkToEmail:(nonnull NSString *)email + actionCodeSettings:(nonnull FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRSendSignInLinkToEmailCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + if (!email) { + [FIRAuthExceptionUtils + raiseInvalidParameterExceptionWithReason:kMissingEmailInvalidParameterExceptionReason]; + } + + if (!actionCodeSettings.handleCodeInApp) { + [FIRAuthExceptionUtils + raiseInvalidParameterExceptionWithReason:kHandleCodeInAppFalseExceptionReason]; + } + FIRGetOOBConfirmationCodeRequest *request = + [FIRGetOOBConfirmationCodeRequest signInWithEmailLinkRequest:email + actionCodeSettings:actionCodeSettings + requestConfiguration:self->_requestConfiguration]; + [FIRAuthBackend getOOBConfirmationCode:request + callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response, + NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(error); + }); + } + }]; + }); +} + +- (void)updateCurrentUser:(FIRUser *)user completion:(nullable FIRUserUpdateCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + if (!user) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion([FIRAuthErrorUtils nullUserErrorWithMessage:nil]); + }); + } + return; + } + void (^updateUserBlock)(FIRUser *user) = ^(FIRUser *user) { + NSError *error; + [self updateCurrentUser:user byForce:YES savingToDisk:YES error:(&error)]; + if (error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(error); + }); + } + return; + } + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(nil); + }); + } + }; + if (![user.requestConfiguration.APIKey isEqualToString:self->_requestConfiguration.APIKey]) { + // If the API keys are different, then we need to confirm that the user belongs to the same + // project before proceeding. + user.requestConfiguration = self->_requestConfiguration; + [user reloadWithCompletion:^(NSError *_Nullable error) { + if (error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(error); + }); + } + return; + } + updateUserBlock(user); + }]; + } else { + updateUserBlock(user); + } + }); +} + +- (BOOL)signOut:(NSError *_Nullable __autoreleasing *_Nullable)error { + __block BOOL result = YES; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + if (!self->_currentUser) { + return; + } + result = [self updateCurrentUser:nil byForce:NO savingToDisk:YES error:error]; + }); + return result; +} + +- (BOOL)signOutByForceWithUserID:(NSString *)userID error:(NSError *_Nullable *_Nullable)error { + if (_currentUser.uid != userID) { + return YES; + } + return [self updateCurrentUser:nil byForce:YES savingToDisk:YES error:error]; +} + +- (BOOL)isSignInWithEmailLink:(NSString *)link { + if (link.length == 0) { + return NO; + } + NSDictionary *queryItems = [FIRAuthWebUtils parseURL:link]; + if (![queryItems count]) { + NSURLComponents *urlComponents = [NSURLComponents componentsWithString:link]; + if (!urlComponents.query) { + return NO; + } + queryItems = [FIRAuthWebUtils parseURL:urlComponents.query]; + } + + if (![queryItems count]) { + return NO; + } + + NSString *actionCode = queryItems[@"oobCode"]; + NSString *mode = queryItems[@"mode"]; + + if (actionCode && [mode isEqualToString:@"signIn"]) { + return YES; + } + return NO; +} + +- (FIRAuthStateDidChangeListenerHandle)addAuthStateDidChangeListener: + (FIRAuthStateDidChangeListenerBlock)listener { + __block BOOL firstInvocation = YES; + __block NSString *previousUserID; + return [self addIDTokenDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) { + BOOL shouldCallListener = firstInvocation || !(previousUserID == user.uid || + [previousUserID isEqualToString:user.uid]); + firstInvocation = NO; + previousUserID = [user.uid copy]; + if (shouldCallListener) { + listener(auth, user); + } + }]; +} + +- (void)removeAuthStateDidChangeListener:(FIRAuthStateDidChangeListenerHandle)listenerHandle { + [self removeIDTokenDidChangeListener:listenerHandle]; +} + +- (FIRIDTokenDidChangeListenerHandle)addIDTokenDidChangeListener: + (FIRIDTokenDidChangeListenerBlock)listener { + if (!listener) { + [NSException raise:NSInvalidArgumentException format:@"listener must not be nil."]; + return nil; + } + FIRAuthStateDidChangeListenerHandle handle; + NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter]; + handle = [notifications addObserverForName:FIRAuthStateDidChangeNotification + object:self + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification *_Nonnull notification) { + FIRAuth *auth = notification.object; + listener(auth, auth.currentUser); + }]; + @synchronized(self) { + [_listenerHandles addObject:handle]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + listener(self, self->_currentUser); + }); + return handle; +} + +- (void)removeIDTokenDidChangeListener:(FIRIDTokenDidChangeListenerHandle)listenerHandle { + [[NSNotificationCenter defaultCenter] removeObserver:listenerHandle]; + @synchronized(self) { + [_listenerHandles removeObject:listenerHandle]; + } +} + +- (void)useAppLanguage { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + self->_requestConfiguration.languageCode = [[NSLocale preferredLanguages] firstObject]; + }); +} + +- (nullable NSString *)languageCode { + return _requestConfiguration.languageCode; +} + +- (void)setLanguageCode:(nullable NSString *)languageCode { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + self->_requestConfiguration.languageCode = [languageCode copy]; + }); +} + +- (nullable NSString *)additionalFrameworkMarker { + return self->_requestConfiguration.additionalFrameworkMarker; +} + +- (void)setAdditionalFrameworkMarker:(nullable NSString *)additionalFrameworkMarker { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + self->_requestConfiguration.additionalFrameworkMarker = [additionalFrameworkMarker copy]; + }); +} + +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-property-ivar" +// The warning is ignored because we use the token manager to get the token, instead of using the +// ivar. +- (nullable NSData *)APNSToken { + __block NSData *result = nil; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = self->_tokenManager.token.data; + }); + return result; +} +#pragma clang diagnostic pop + +#pragma mark - UIApplicationDelegate + +- (void)application:(UIApplication *)application + didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + [self setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeUnknown]; +} + +- (void)application:(UIApplication *)application + didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + [self->_tokenManager cancelWithError:error]; + }); +} + +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + [self canHandleNotification:userInfo]; +} + +// iOS 10 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo { + [self canHandleNotification:userInfo]; +} +#pragma clang diagnostic pop + +- (BOOL)application:(UIApplication *)app + openURL:(NSURL *)url + options:(NSDictionary *)options { + return [self canHandleURL:url]; +} + +// iOS 10 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + sourceApplication:(nullable NSString *)sourceApplication + annotation:(id)annotation { + return [self canHandleURL:url]; +} +#pragma clang diagnostic pop + +- (void)setAPNSToken:(NSData *)token type:(FIRAuthAPNSTokenType)type { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + self->_tokenManager.token = [[FIRAuthAPNSToken alloc] initWithData:token type:type]; + }); +} + +- (BOOL)canHandleNotification:(NSDictionary *)userInfo { + __block BOOL result = NO; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = [self->_notificationManager canHandleNotification:userInfo]; + }); + return result; +} + +- (BOOL)canHandleURL:(NSURL *)URL { + __block BOOL result = NO; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = [self->_authURLPresenter canHandleURL:URL]; + }); + return result; +} + +#pragma mark - UISceneDelegate +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 +- (void)scene:(UIScene *)scene + openURLContexts:(NSSet *)URLContexts API_AVAILABLE(ios(13.0)) { + for (UIOpenURLContext *urlContext in URLContexts) { + NSURL *url = [urlContext URL]; + [self canHandleURL:url]; + } +} +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 +#endif // TARGET_OS_IOS + +#pragma mark - Internal Methods + +#if TARGET_OS_IOS +/** @fn signInWithPhoneCredential:callback: + @brief Signs in using a phone credential. + @param credential The Phone Auth credential used to sign in. + @param operation The type of operation for which this sign-in attempt is initiated. + @param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked + asynchronously on the global auth work queue in the future. + */ +- (void)signInWithPhoneCredential:(FIRPhoneAuthCredential *)credential + operation:(FIRAuthOperationType)operation + callback:(FIRVerifyPhoneNumberResponseCallback)callback { + if (credential.temporaryProof.length && credential.phoneNumber.length) { + FIRVerifyPhoneNumberRequest *request = + [[FIRVerifyPhoneNumberRequest alloc] initWithTemporaryProof:credential.temporaryProof + phoneNumber:credential.phoneNumber + operation:operation + requestConfiguration:_requestConfiguration]; + [FIRAuthBackend verifyPhoneNumber:request callback:callback]; + return; + } + + if (!credential.verificationID.length) { + callback(nil, [FIRAuthErrorUtils missingVerificationIDErrorWithMessage:nil]); + return; + } + if (!credential.verificationCode.length) { + callback(nil, [FIRAuthErrorUtils missingVerificationCodeErrorWithMessage:nil]); + return; + } + FIRVerifyPhoneNumberRequest *request = + [[FIRVerifyPhoneNumberRequest alloc] initWithVerificationID:credential.verificationID + verificationCode:credential.verificationCode + operation:operation + requestConfiguration:_requestConfiguration]; + [FIRAuthBackend verifyPhoneNumber:request callback:callback]; +} + +#endif + +/** @fn internalSignInAndRetrieveDataWithCustomToken:completion: + @brief Signs in a Firebase user given a custom token. + @param token A self-signed custom auth token. + @param completion A block which is invoked when the custom token sign in request completes. + */ +- (void)internalSignInAndRetrieveDataWithCustomToken:(NSString *)token + completion: + (nullable FIRAuthDataResultCallback)completion { + FIRVerifyCustomTokenRequest *request = + [[FIRVerifyCustomTokenRequest alloc] initWithToken:token + requestConfiguration:_requestConfiguration]; + [FIRAuthBackend + verifyCustomToken:request + callback:^(FIRVerifyCustomTokenResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (completion) { + completion(nil, error); + return; + } + } + [self completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + if (error && completion) { + completion(nil, error); + return; + } + FIRAdditionalUserInfo *additonalUserInfo = + [[FIRAdditionalUserInfo alloc] + initWithProviderID:nil + profile:nil + username:nil + isNewUser:response.isNewUser]; + FIRAuthDataResult *result = + user ? [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:additonalUserInfo] + : nil; + if (completion) { + completion(result, error); + } + }]; + }]; +} + +/** @fn internalCreateUserWithEmail:password:completion: + @brief Makes a backend request attempting to create a new Firebase user given an email address + and password. + @param email The email address used to create the new Firebase user. + @param password The password used to create the new Firebase user. + @param completion Optionally; a block which is invoked when the request finishes. + */ +- (void)internalCreateUserWithEmail:(NSString *)email + password:(NSString *)password + completion:(nullable FIRSignupNewUserCallback)completion { + FIRSignUpNewUserRequest *request = + [[FIRSignUpNewUserRequest alloc] initWithEmail:email + password:password + displayName:nil + requestConfiguration:_requestConfiguration]; + if (![request.password length]) { + completion( + nil, [FIRAuthErrorUtils weakPasswordErrorWithServerResponseReason:kMissingPasswordReason]); + return; + } + if (![request.email length]) { + completion(nil, [FIRAuthErrorUtils missingEmailErrorWithMessage:nil]); + return; + } + [FIRAuthBackend signUpNewUser:request callback:completion]; +} + +/** @fn internalSignInAnonymouslyWithCompletion: + @param completion A block which is invoked when the anonymous sign in request completes. + */ +- (void)internalSignInAnonymouslyWithCompletion:(FIRSignupNewUserCallback)completion { + FIRSignUpNewUserRequest *request = + [[FIRSignUpNewUserRequest alloc] initWithRequestConfiguration:_requestConfiguration]; + [FIRAuthBackend signUpNewUser:request callback:completion]; +} + +/** @fn possiblyPostAuthStateChangeNotification + @brief Posts the auth state change notificaton if current user's token has been changed. + */ +- (void)possiblyPostAuthStateChangeNotification { + NSString *token = _currentUser.rawAccessToken; + if (_lastNotifiedUserToken == token || + (token != nil && [_lastNotifiedUserToken isEqualToString:token])) { + return; + } + _lastNotifiedUserToken = token; + if (_autoRefreshTokens) { + // Shedule new refresh task after successful attempt. + [self scheduleAutoTokenRefresh]; + } + NSMutableDictionary *internalNotificationParameters = [NSMutableDictionary dictionary]; + if (self.app) { + internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationAppKey] = self.app; + } + if (token.length) { + internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationTokenKey] = token; + } + internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationUIDKey] = + _currentUser.uid; + NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter]; + dispatch_async(dispatch_get_main_queue(), ^{ + [notifications postNotificationName:FIRAuthStateDidChangeInternalNotification + object:self + userInfo:internalNotificationParameters]; + [notifications postNotificationName:FIRAuthStateDidChangeNotification object:self]; + }); +} + +- (BOOL)updateKeychainWithUser:(FIRUser *)user error:(NSError *_Nullable *_Nullable)error { + if (user != _currentUser) { + // No-op if the user is no longer signed in. This is not considered an error as we don't check + // whether the user is still current on other callbacks of user operations either. + return YES; + } + if ([self saveUser:user error:error]) { + [self possiblyPostAuthStateChangeNotification]; + return YES; + } + return NO; +} + +/** @fn setKeychainServiceNameForApp + @brief Sets the keychain service name global data for the particular app. + @param app The Firebase app to set keychain service name for. + */ ++ (void)setKeychainServiceNameForApp:(FIRApp *)app { + @synchronized(self) { + gKeychainServiceNameForAppName[app.name] = + [@"firebase_auth_" stringByAppendingString:app.options.googleAppID]; + } +} + +/** @fn keychainServiceNameForAppName: + @brief Gets the keychain service name global data for the particular app by name. + @param appName The name of the Firebase app to get keychain service name for. + */ ++ (NSString *)keychainServiceNameForAppName:(NSString *)appName { + @synchronized(self) { + return gKeychainServiceNameForAppName[appName]; + } +} + +/** @fn deleteKeychainServiceNameForAppName: + @brief Deletes the keychain service name global data for the particular app by name. + @param appName The name of the Firebase app to delete keychain service name for. + */ ++ (void)deleteKeychainServiceNameForAppName:(NSString *)appName { + @synchronized(self) { + [gKeychainServiceNameForAppName removeObjectForKey:appName]; + } +} + +/** @fn scheduleAutoTokenRefreshWithDelay: + @brief Schedules a task to automatically refresh tokens on the current user. The token refresh + is scheduled 5 minutes before the scheduled expiration time. + @remarks If the token expires in less than 5 minutes, schedule the token refresh immediately. + */ +- (void)scheduleAutoTokenRefresh { + NSTimeInterval tokenExpirationInterval = + [_currentUser.accessTokenExpirationDate timeIntervalSinceNow] - kTokenRefreshHeadStart; + [self scheduleAutoTokenRefreshWithDelay:MAX(tokenExpirationInterval, 0) retry:NO]; +} + +/** @fn scheduleAutoTokenRefreshWithDelay: + @brief Schedules a task to automatically refresh tokens on the current user. + @param delay The delay in seconds after which the token refresh task should be scheduled to be + executed. + @param retry Flag to determine whether the invocation is a retry attempt or not. + */ +- (void)scheduleAutoTokenRefreshWithDelay:(NSTimeInterval)delay retry:(BOOL)retry { + NSString *accessToken = _currentUser.rawAccessToken; + if (!accessToken) { + return; + } + if (retry) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000003", + @"Token auto-refresh re-scheduled in %02d:%02d " + @"because of error on previous refresh attempt.", + (int)ceil(delay) / 60, (int)ceil(delay) % 60); + } else { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000004", + @"Token auto-refresh scheduled in %02d:%02d for the new token.", + (int)ceil(delay) / 60, (int)ceil(delay) % 60); + } + _autoRefreshScheduled = YES; + __weak FIRAuth *weakSelf = self; + [[FIRAuthDispatcher sharedInstance] + dispatchAfterDelay:delay + queue:FIRAuthGlobalWorkQueue() + task:^(void) { + FIRAuth *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + if (![strongSelf->_currentUser.rawAccessToken isEqualToString:accessToken]) { + // Another auto refresh must have been scheduled, so keep + // _autoRefreshScheduled unchanged. + return; + } + strongSelf->_autoRefreshScheduled = NO; + if (strongSelf->_isAppInBackground) { + return; + } + NSString *uid = strongSelf->_currentUser.uid; + [strongSelf->_currentUser + internalGetTokenForcingRefresh:YES + callback:^(NSString *_Nullable token, + NSError *_Nullable error) { + if (![strongSelf->_currentUser.uid + isEqualToString:uid]) { + return; + } + if (error) { + // Kicks off exponential back off logic to retry + // failed attempt. Starts with one minute delay + // (60 seconds) if this is the first failed + // attempt. + NSTimeInterval rescheduleDelay; + if (retry) { + rescheduleDelay = + MIN(delay * 2, kMaxWaitTimeForBackoff); + } else { + rescheduleDelay = 60; + } + [strongSelf + scheduleAutoTokenRefreshWithDelay: + rescheduleDelay + retry:YES]; + } + }]; + }]; +} + +#pragma mark - + +/** @fn completeSignInWithTokenService:callback: + @brief Completes a sign-in flow once we have access and refresh tokens for the user. + @param accessToken The STS access token. + @param accessTokenExpirationDate The approximate expiration date of the access token. + @param refreshToken The STS refresh token. + @param anonymous Whether or not the user is anonymous. + @param callback Called when the user has been signed in or when an error occurred. Invoked + asynchronously on the global auth work queue in the future. + */ +- (void)completeSignInWithAccessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(nullable NSString *)refreshToken + anonymous:(BOOL)anonymous + callback:(FIRAuthResultCallback)callback { + [FIRUser retrieveUserWithAuth:self + accessToken:accessToken + accessTokenExpirationDate:accessTokenExpirationDate + refreshToken:refreshToken + anonymous:anonymous + callback:callback]; +} + +/** @fn signInFlowAuthResultCallbackByDecoratingCallback: + @brief Creates a FIRAuthResultCallback block which wraps another FIRAuthResultCallback; trying + to update the current user before forwarding it's invocations along to a subject block + @param callback Called when the user has been updated or when an error has occurred. Invoked + asynchronously on the main thread in the future. + @return Returns a block that updates the current user. + @remarks Typically invoked as part of the complete sign-in flow. For any other uses please + consider alternative ways of updating the current user. +*/ +- (FIRAuthResultCallback)signInFlowAuthResultCallbackByDecoratingCallback: + (nullable FIRAuthResultCallback)callback { + return ^(FIRUser *_Nullable user, NSError *_Nullable error) { + if (error) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + if (![self updateCurrentUser:user byForce:NO savingToDisk:YES error:&error]) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(user, nil); + }); + } + }; +} + +/** @fn signInFlowAuthDataResultCallbackByDecoratingCallback: + @brief Creates a FIRAuthDataResultCallback block which wraps another FIRAuthDataResultCallback; + trying to update the current user before forwarding it's invocations along to a subject + block. + @param callback Called when the user has been updated or when an error has occurred. Invoked + asynchronously on the main thread in the future. + @return Returns a block that updates the current user. + @remarks Typically invoked as part of the complete sign-in flow. For any other uses please + consider alternative ways of updating the current user. +*/ +- (FIRAuthDataResultCallback)signInFlowAuthDataResultCallbackByDecoratingCallback: + (nullable FIRAuthDataResultCallback)callback { + return ^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { + if (error) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + if (![self updateCurrentUser:authResult.user byForce:NO savingToDisk:YES error:&error]) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(authResult, nil); + }); + } + }; +} + +#pragma mark - User-Related Methods + +/** @fn updateCurrentUser:byForce:savingToDisk:error: + @brief Update the current user; initializing the user's internal properties correctly, and + optionally saving the user to disk. + @remarks This method is called during: sign in and sign out events, as well as during class + initialization time. The only time the saveToDisk parameter should be set to NO is during + class initialization time because the user was just read from disk. + @param user The user to use as the current user (including nil, which is passed at sign out + time.) + @param saveToDisk Indicates the method should persist the user data to disk. + */ +- (BOOL)updateCurrentUser:(nullable FIRUser *)user + byForce:(BOOL)force + savingToDisk:(BOOL)saveToDisk + error:(NSError *_Nullable *_Nullable)error { + if (user == _currentUser) { + [self possiblyPostAuthStateChangeNotification]; + return YES; + } + BOOL success = YES; + if (saveToDisk) { + success = [self saveUser:user error:error]; + } + if (success || force) { + _currentUser = user; + [self possiblyPostAuthStateChangeNotification]; + } + return success; +} + +/** @fn saveUser:error: + @brief Persists user. + @param user The user to save. + @param outError Return value for any error which occurs. + @return @YES on success, @NO otherwise. + */ +- (BOOL)saveUser:(nullable FIRUser *)user error:(NSError *_Nullable *_Nullable)outError { + BOOL success; + + if (!self.userAccessGroup) { + NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName]; + if (!user) { + success = [_keychainServices removeDataForKey:userKey error:outError]; + } else { + // Encode the user object. + NSMutableData *archiveData = [NSMutableData data]; +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = + [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData]; +#pragma clang diagnostic pop + [archiver encodeObject:user forKey:userKey]; + [archiver finishEncoding]; + + // Save the user object's encoded value. + success = [_keychainServices setData:archiveData forKey:userKey error:outError]; + } + } else { + if (!user) { + success = [self.storedUserManager removeStoredUserForAccessGroup:self.userAccessGroup + projectIdentifier:self.app.options.APIKey + error:outError]; + } else { + success = [self.storedUserManager setStoredUser:user + forAccessGroup:self.userAccessGroup + projectIdentifier:self.app.options.APIKey + error:outError]; + } + } + + return success; +} + +/** @fn getUser:error: + @brief Retrieves the saved user associated, if one exists, from the keychain. + @param outUser An out parameter which is populated with the saved user, if one exists. + @param error Return value for any error which occurs. + @return YES if the operation was a success (irrespective of whether or not a saved user existed + for the given @c firebaseAppId,) NO if an error occurred. + */ +- (BOOL)getUser:(FIRUser *_Nullable *)outUser error:(NSError *_Nullable *_Nullable)error { + if (!self.userAccessGroup) { + NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName]; + + NSError *keychainError; + NSData *encodedUserData = [_keychainServices dataForKey:userKey error:&keychainError]; + if (keychainError) { + if (error) { + *error = keychainError; + } + return NO; + } + if (!encodedUserData) { + *outUser = nil; + return YES; + } +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = + [[NSKeyedUnarchiver alloc] initForReadingWithData:encodedUserData]; +#pragma clang diagnostic pop + FIRUser *user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey]; + user.auth = self; + *outUser = user; + + return YES; + } else { + FIRUser *user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup + projectIdentifier:self.app.options.APIKey + error:error]; + user.auth = self; + *outUser = user; + if (user) { + return YES; + } else { + if (error && *error) { + return NO; + } else { + return YES; + } + } + } +} + +#pragma mark - Interoperability + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock authCreationBlock = + ^id _Nullable(FIRComponentContainer *_Nonnull container, BOOL *_Nonnull isCacheable) { + *isCacheable = YES; + return [[FIRAuth alloc] initWithApp:container.app]; + }; + FIRComponent *authInterop = [FIRComponent componentWithProtocol:@protocol(FIRAuthInterop) + instantiationTiming:FIRInstantiationTimingAlwaysEager + dependencies:@[] + creationBlock:authCreationBlock]; + return @[ authInterop ]; +} + +#pragma mark - FIRComponentLifecycleMaintainer + +- (void)appWillBeDeleted:(nonnull FIRApp *)app { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + // This doesn't stop any request already issued, see b/27704535 . + NSString *keychainServiceName = [FIRAuth keychainServiceNameForAppName:app.name]; + if (keychainServiceName) { + [[self class] deleteKeychainServiceNameForAppName:app.name]; + FIRAuthKeychainServices *keychain = + [[FIRAuthKeychainServices alloc] initWithService:keychainServiceName]; + NSString *userKey = [NSString stringWithFormat:kUserKey, app.name]; + [keychain removeDataForKey:userKey error:NULL]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + // TODO: Move over to fire an event instead, once ready. + [[NSNotificationCenter defaultCenter] postNotificationName:FIRAuthStateDidChangeNotification + object:nil]; + }); + }); +} + +#pragma mark - FIRAuthInterop + +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback { + __weak FIRAuth *weakSelf = self; + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuth *strongSelf = weakSelf; + // Enable token auto-refresh if not aleady enabled. + if (strongSelf && !strongSelf->_autoRefreshTokens) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000002", @"Token auto-refresh enabled."); + strongSelf->_autoRefreshTokens = YES; + [strongSelf scheduleAutoTokenRefresh]; + +#if TARGET_OS_IOS || TARGET_OS_TV // TODO: Is a similar mechanism needed on macOS? + strongSelf->_applicationDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] + addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:nil + usingBlock:^(NSNotification *notification) { + FIRAuth *strongSelf = weakSelf; + if (strongSelf) { + strongSelf->_isAppInBackground = NO; + if (!strongSelf->_autoRefreshScheduled) { + [weakSelf scheduleAutoTokenRefresh]; + } + } + }]; + strongSelf->_applicationDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] + addObserverForName:UIApplicationDidEnterBackgroundNotification + object:nil + queue:nil + usingBlock:^(NSNotification *notification) { + FIRAuth *strongSelf = weakSelf; + if (strongSelf) { + strongSelf->_isAppInBackground = YES; + } + }]; +#endif + } + // Call back with 'nil' if there is no current user. + if (!strongSelf || !strongSelf->_currentUser) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, nil); + }); + return; + } + // Call back with current user token. + [strongSelf->_currentUser + internalGetTokenForcingRefresh:forceRefresh + callback:^(NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(token, error); + }); + }]; + }); +} + +- (nullable NSString *)getUserID { + return _currentUser.uid; +} + +#pragma mark - Keychain sharing + +- (BOOL)internalUseUserAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError { + BOOL success; + success = [self.storedUserManager setStoredUserAccessGroup:accessGroup error:outError]; + if (!success) { + return NO; + } + + FIRUser *user = [self getStoredUserForAccessGroup:accessGroup error:outError]; + if (!user && outError && *outError) { + return NO; + } + success = [self updateCurrentUser:user byForce:NO savingToDisk:NO error:outError]; + if (!success) { + return NO; + } + + if (_userAccessGroup == nil && accessGroup != nil) { + NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName]; + [_keychainServices removeDataForKey:userKey error:outError]; + } + _userAccessGroup = accessGroup; + self->_lastNotifiedUserToken = user.rawAccessToken; + + return YES; +} + +- (BOOL)useUserAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError { + // self.storedUserManager is initialized asynchronously. Make sure it is done. + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + }); + return [self internalUseUserAccessGroup:accessGroup error:outError]; +} + +- (nullable FIRUser *)getStoredUserForAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError { + FIRUser *user; + if (!accessGroup) { + NSString *userKey = [NSString stringWithFormat:kUserKey, _firebaseAppName]; + NSData *encodedUserData = [_keychainServices dataForKey:userKey error:outError]; + if (!encodedUserData) { + return nil; + } + +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = + [[NSKeyedUnarchiver alloc] initForReadingWithData:encodedUserData]; +#pragma clang diagnostic pop + user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:userKey]; + } else { + user = [self.storedUserManager getStoredUserForAccessGroup:self.userAccessGroup + projectIdentifier:self.app.options.APIKey + error:outError]; + } + + user.auth = self; + return user; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult.m new file mode 100644 index 00000000..d4c7c2be --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult.m @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthDataResult + +/** @var kAdditionalUserInfoCodingKey + @brief The key used to encode the additionalUserInfo property for NSSecureCoding. + */ +static NSString *const kAdditionalUserInfoCodingKey = @"additionalUserInfo"; + +/** @var kUserCodingKey + @brief The key used to encode the user property for NSSecureCoding. + */ +static NSString *const kUserCodingKey = @"user"; + +/** @var kCredentialCodingKey + @brief The key used to encode the credential for NSSecureCoding. + */ +static NSString *const kCredentialCodingKey = @"credential"; + +- (nullable instancetype)initWithUser:(FIRUser *)user + additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo { + return [self initWithUser:user additionalUserInfo:additionalUserInfo credential:nil]; +} + +- (nullable instancetype)initWithUser:(FIRUser *)user + additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo + credential:(nullable FIROAuthCredential *)credential { + self = [super init]; + if (self) { + _additionalUserInfo = additionalUserInfo; + _user = user; + _credential = credential; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + FIRUser *user = [aDecoder decodeObjectOfClass:[FIRUser class] forKey:kUserCodingKey]; + FIRAdditionalUserInfo *additionalUserInfo = + [aDecoder decodeObjectOfClass:[FIRAdditionalUserInfo class] + forKey:kAdditionalUserInfoCodingKey]; + FIROAuthCredential *credential = [aDecoder decodeObjectOfClass:[FIROAuthCredential class] + forKey:kCredentialCodingKey]; + return [self initWithUser:user additionalUserInfo:additionalUserInfo credential:credential]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_user forKey:kUserCodingKey]; + [aCoder encodeObject:_additionalUserInfo forKey:kAdditionalUserInfoCodingKey]; + [aCoder encodeObject:_credential forKey:kCredentialCodingKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h new file mode 100644 index 00000000..30c5ec7e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthDataResult () + +/** @fn initWithUser:additionalUserInfo: + @brief Designated initializer. + @param user The signed in user reference. + @param additionalUserInfo The additional user info if available. + */ +- (nullable instancetype)initWithUser:(FIRUser *)user + additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo; + +/** @fn initWithUser:additionalUserInfo: + @brief Designated initializer. + @param user The signed in user reference. + @param additionalUserInfo The additional user info if available. + @param credential The updated OAuth credential if available. + */ +- (nullable instancetype)initWithUser:(FIRUser *)user + additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo + credential:(nullable FIROAuthCredential *)credential + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h new file mode 100644 index 00000000..2c5839b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthDispatcherImplBlock + @brief The type of block which can be set as the implementation for @c + dispatchAfterDelay:queue:callback: . + + @param delay The delay in seconds after which the task will be scheduled to execute. + @param queue The dispatch queue on which the task will be submitted. + @param task The task (block) to be scheduled for future execution. + */ +typedef void (^FIRAuthDispatcherImplBlock)(NSTimeInterval delay, + dispatch_queue_t queue, + void (^task)(void)); + +/** @class FIRAuthDispatchAfter + @brief A utility class used to facilitate scheduling tasks to be executed in the future. + */ +@interface FIRAuthDispatcher : NSObject + +/** @property dispatchAfterImplementation + @brief Allows custom implementation of dispatchAfterDelay:queue:callback:. + @remarks Set to nil to restore default implementation. + */ +@property(nonatomic, nullable, copy) FIRAuthDispatcherImplBlock dispatchAfterImplementation; + +/** @fn dispatchAfterDelay:queue:callback: + @brief Schedules task in the future after a specified delay. + + @param delay The delay in seconds after which the task will be scheduled to execute. + @param queue The dispatch queue on which the task will be submitted. + @param task The task (block) to be scheduled for future execution. + */ +- (void)dispatchAfterDelay:(NSTimeInterval)delay + queue:(dispatch_queue_t)queue + task:(void (^)(void))task; + +/** @fn sharedInstance + @brief Gets the shared instance of this class. + @returns The shared instance of this clss + */ ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.m new file mode 100644 index 00000000..e5e32c39 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthDispatcher.m @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthDispatcher + +@synthesize dispatchAfterImplementation = _dispatchAfterImplementation; + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static FIRAuthDispatcher *sharedInstance; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (void)dispatchAfterDelay:(NSTimeInterval)delay + queue:(dispatch_queue_t)queue + task:(void (^)(void))task { + if (_dispatchAfterImplementation) { + _dispatchAfterImplementation(delay, queue, task); + return; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), queue, task); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h new file mode 100644 index 00000000..55bb1a70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @fn FIRAuthGlobalWorkQueue + @brief Retrieves the global serial work queue for Firebase Auth. + @return The global serial dispatch queue. + @remarks To ensure thread safety, all auth code must be executed in either this global work + queue, or a serial queue that has its target queue set to this work queue. All public method + implementations that may involve contested code shall dispatch to this work queue as the + first thing they do. + */ +extern dispatch_queue_t FIRAuthGlobalWorkQueue(void); + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.m new file mode 100644 index 00000000..bfe263a7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" + +NS_ASSUME_NONNULL_BEGIN + +dispatch_queue_t FIRAuthGlobalWorkQueue() { + static dispatch_once_t once; + static dispatch_queue_t queue; + dispatch_once(&once, ^{ + queue = dispatch_queue_create("com.google.firebase.auth.globalWorkQueue", NULL); + }); + return queue; +} + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthOperationType.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthOperationType.h new file mode 100644 index 00000000..62d6cd10 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthOperationType.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief Indicates the type of operation performed for RPCs that support the operation + parameter. + */ +typedef NS_ENUM(NSInteger, FIRAuthOperationType) { + /** Indicates that the operation type is uspecified. + */ + FIRAuthOperationTypeUnspecified = 0, + + /** Indicates that the operation type is sign in or sign up. + */ + FIRAuthOperationTypeSignUpOrSignIn = 1, + + /** Indicates that the operation type is reauthentication. + */ + FIRAuthOperationTypeReauth = 2, + + /** Indicates that the operation type is update. + */ + FIRAuthOperationTypeUpdate = 3, + + /** Indicates that the operation type is link. + */ + FIRAuthOperationTypeLink = 4, +}; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h new file mode 100644 index 00000000..cdae0468 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthSerialTaskCompletionBlock + @brief The type of method a @c FIRAuthSerialTask must call when it is complete. + */ +typedef void (^FIRAuthSerialTaskCompletionBlock)(void); + +/** @typedef FIRAuthSerialTask + @brief Represents a unit of work submitted to a task queue. + @param complete The task MUST call the complete method when done. + */ +typedef void (^FIRAuthSerialTask)(FIRAuthSerialTaskCompletionBlock complete); + +/** @class FIRAuthSerialTaskQueue + @brief An easy to use serial task queue which supports a callback-based completion notification + system for easy asyncronous call chaining. + */ +@interface FIRAuthSerialTaskQueue : NSObject + +/** @fn enqueueTask: + @brief Enqueues a task for serial execution in the queue. + @remarks The task MUST call the complete method when done. This method is thread-safe. + The task block won't be executed concurrently with any other blocks in other task queues or + the global work queue as returned by @c FIRAuthGlobalWorkQueue , but an uncompleted task + (e.g. task block finished executation before complete method is called at a later time) + does not affect other task queues or the global work queue. + */ +- (void)enqueueTask:(FIRAuthSerialTask)task; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.m new file mode 100644 index 00000000..4bded783 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.m @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthSerialTaskQueue { + /** @var _dispatchQueue + @brief The asyncronous dispatch queue into which tasks are enqueued and processed + serially. + */ + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _dispatchQueue = dispatch_queue_create("com.google.firebase.auth.serialTaskQueue", NULL); + dispatch_set_target_queue(_dispatchQueue, FIRAuthGlobalWorkQueue()); + } + return self; +} + +- (void)enqueueTask:(FIRAuthSerialTask)task { + // This dispatch queue will run tasks serially in FIFO order, as long as it's not suspended. + dispatch_async(self->_dispatchQueue, ^{ + // But as soon as a task is started, stop other tasks from running until the task calls it's + // completion handler, which allows the queue to resume processing of tasks. This allows the + // task to perform other asyncronous actions on other dispatch queues and "get back to us" when + // all of their sub-tasks are complete. + dispatch_suspend(self->_dispatchQueue); + task(^{ + dispatch_resume(self->_dispatchQueue); + }); + }); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSettings.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSettings.m new file mode 100644 index 00000000..32dc65c7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthSettings.m @@ -0,0 +1,33 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthSettings + +- (instancetype)init { + self = [super init]; + if (self) { + _appVerificationDisabledForTesting = NO; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult.m new file mode 100644 index 00000000..fd857e30 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult.m @@ -0,0 +1,166 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kExpirationDateKey + @brief The key used to encode the expirationDate property for NSSecureCoding. + */ +static NSString *const kExpirationDateKey = @"expiratinDate"; + +/** @var kTokenKey + @brief The key used to encode the token property for NSSecureCoding. + */ +static NSString *const kTokenKey = @"token"; + +/** @var kAuthDateKey + @brief The key used to encode the authDate property for NSSecureCoding. + */ +static NSString *const kAuthDateKey = @"authDate"; + +/** @var kIssuedDateKey + @brief The key used to encode the issuedDate property for NSSecureCoding. + */ +static NSString *const kIssuedDateKey = @"issuedDate"; + +/** @var kSignInProviderKey + @brief The key used to encode the signInProvider property for NSSecureCoding. + */ +static NSString *const kSignInProviderKey = @"signInProvider"; + +/** @var kSignInSecondFactorKey + @brief The key used to encode the signInSecondFactor property for NSSecureCoding. + */ +static NSString *const kSignInSecondFactorKey = @"signInSecondFactor"; + +/** @var kClaimsKey + @brief The key used to encode the claims property for NSSecureCoding. + */ +static NSString *const kClaimsKey = @"claims"; + +@implementation FIRAuthTokenResult + +- (instancetype)initWithToken:(NSString *)token + expirationDate:(NSDate *)expirationDate + authDate:(NSDate *)authDate + issuedAtDate:(NSDate *)issuedAtDate + signInProvider:(NSString *)signInProvider + signInSecondFactor:(NSString *)signInSecondFactor + claims:(NSDictionary *)claims { + self = [super init]; + if (self) { + _token = token; + _expirationDate = expirationDate; + _authDate = authDate; + _issuedAtDate = issuedAtDate; + _signInProvider = signInProvider; + _signInSecondFactor = signInSecondFactor; + _claims = claims; + } + return self; +} + ++ (nullable FIRAuthTokenResult *)tokenResultWithToken:(NSString *)token { + NSArray *tokenStringArray = [token componentsSeparatedByString:@"."]; + + // The JWT should have three parts, though we only use the second in this method. + if (tokenStringArray.count != 3) { + return nil; + } + + // The token payload is always the second index of the array. + NSString *IDToken = tokenStringArray[1]; + + // Convert the base64URL encoded string to a base64 encoded string. + // Replace "_" with "/" + NSMutableString *tokenPayload = [[IDToken stringByReplacingOccurrencesOfString:@"_" + withString:@"/"] mutableCopy]; + + // Replace "-" with "+" + [tokenPayload replaceOccurrencesOfString:@"-" + withString:@"+" + options:kNilOptions + range:NSMakeRange(0, tokenPayload.length)]; + + // Pad the token payload with "=" signs if the payload's length is not a multiple of 4. + while ((tokenPayload.length % 4) != 0) { + [tokenPayload appendFormat:@"="]; + } + NSData *decodedTokenPayloadData = + [[NSData alloc] initWithBase64EncodedString:tokenPayload + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + if (!decodedTokenPayloadData) { + return nil; + } + NSError *jsonError = nil; + NSJSONReadingOptions options = NSJSONReadingMutableContainers | NSJSONReadingAllowFragments; + NSDictionary *tokenPayloadDictionary = + [NSJSONSerialization JSONObjectWithData:decodedTokenPayloadData + options:options + error:&jsonError]; + if (jsonError != nil) { + return nil; + } + + if (!tokenPayloadDictionary) { + return nil; + } + + // These are dates since 00:00:00 January 1 1970, as described by the Terminology section in + // the JWT spec. https://tools.ietf.org/html/rfc7519 + NSDate *expirationDate = + [NSDate dateWithTimeIntervalSince1970:[tokenPayloadDictionary[@"exp"] doubleValue]]; + NSDate *authDate = + [NSDate dateWithTimeIntervalSince1970:[tokenPayloadDictionary[@"auth_time"] doubleValue]]; + NSDate *issuedAtDate = + [NSDate dateWithTimeIntervalSince1970:[tokenPayloadDictionary[@"iat"] doubleValue]]; + + NSDictionary *firebaseTokenPayloadDictionary = tokenPayloadDictionary[@"firebase"]; + NSString *signInProvider = firebaseTokenPayloadDictionary[@"sign_in_provider"]; + NSString *signInSecondFactor = firebaseTokenPayloadDictionary[@"sign_in_second_factor"]; + + FIRAuthTokenResult *tokenResult = + [[FIRAuthTokenResult alloc] initWithToken:token + expirationDate:expirationDate + authDate:authDate + issuedAtDate:issuedAtDate + signInProvider:signInProvider + signInSecondFactor:signInSecondFactor + claims:tokenPayloadDictionary]; + return tokenResult; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *token = [aDecoder decodeObjectOfClass:[NSDate class] forKey:kTokenKey]; + return [FIRAuthTokenResult tokenResultWithToken:token]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_token forKey:kTokenKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h new file mode 100644 index 00000000..bffe2eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @extension FIRAuthAPNSTokenResult + @brief An internal class used to expose internal methods of FIRAuthAPNSTokenResult. + */ +@interface FIRAuthTokenResult () + +/** @fn tokenResultWithToken: + @brief Parse a token string to a structured token. + @param token The token string to parse. + @return A structured token result. +*/ ++ (nullable FIRAuthTokenResult *)tokenResultWithToken:(NSString *)token; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth_Internal.h new file mode 100644 index 00000000..0a75ccfd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Auth/FIRAuth_Internal.h @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import "Interop/Auth/Public/FIRAuthInterop.h" + +@class FIRAuthRequestConfiguration; +@class FIRAuthURLPresenter; + +#if TARGET_OS_IOS +@class FIRAuthAPNSTokenManager; +@class FIRAuthAppCredentialManager; +@class FIRAuthNotificationManager; +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuth () + +/** @property requestConfiguration + @brief The configuration object comprising of paramters needed to make a request to Firebase + Auth's backend. + */ +@property(nonatomic, copy, readonly) FIRAuthRequestConfiguration *requestConfiguration; + +#if TARGET_OS_IOS + +/** @property tokenManager + @brief The manager for APNs tokens used by phone number auth. + */ +@property(nonatomic, strong, readonly) FIRAuthAPNSTokenManager *tokenManager; + +/** @property appCredentailManager + @brief The manager for app credentials used by phone number auth. + */ +@property(nonatomic, strong, readonly) FIRAuthAppCredentialManager *appCredentialManager; + +/** @property notificationManager + @brief The manager for remote notifications used by phone number auth. + */ +@property(nonatomic, strong, readonly) FIRAuthNotificationManager *notificationManager; + +#endif // TARGET_OS_IOS + +/** @property authURLPresenter + @brief An object that takes care of presenting URLs via the auth instance. + */ +@property(nonatomic, strong, readonly) FIRAuthURLPresenter *authURLPresenter; + +/** @fn initWithAPIKey:appName: + @brief Designated initializer. + @param APIKey The Google Developers Console API key for making requests from your app. + @param appName The name property of the previously created @c FIRApp instance. + */ +- (nullable instancetype)initWithAPIKey:(NSString *)APIKey + appName:(NSString *)appName NS_DESIGNATED_INITIALIZER; + +/** @fn getUserID + @brief Gets the identifier of the current user, if any. + @return The identifier of the current user, or nil if there is no current user. + */ +- (nullable NSString *)getUserID; + +/** @fn updateKeychainWithUser:error: + @brief Updates the keychain for the given user. + @param user The user to be updated. + @param error The error caused the method to fail if the method returns NO. + @return Whether updating keychain has succeeded or not. + @remarks Called by @c FIRUser when user info or token changes occur. + */ +- (BOOL)updateKeychainWithUser:(FIRUser *)user error:(NSError *_Nullable *_Nullable)error; + +/** @fn internalSignInWithCredential:callback: + @brief Convenience method for @c internalSignInAndRetrieveDataWithCredential:callback: + This method doesn't return additional identity provider data. +*/ +- (void)internalSignInWithCredential:(FIRAuthCredential *)credential + callback:(FIRAuthResultCallback)callback; + +/** @fn internalSignInAndRetrieveDataWithCredential:callback: + @brief Asynchronously signs in Firebase with the given 3rd party credentials (e.g. a Facebook + login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional + identity provider data. + @param credential The credential supplied by the IdP. + @param isReauthentication Indicates whether or not the current invocation originated from an + attempt to reauthenticate. + @param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked + asynchronously on the auth global work queue in the future. + @remarks This is the internal counterpart of this method, which uses a callback that does not + update the current user. + */ +- (void)internalSignInAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + isReauthentication:(BOOL)isReauthentication + callback:(nullable FIRAuthDataResultCallback)callback; + +/** @fn signOutByForceWithUserID:error: + @brief Signs out the current user. + @param userID The ID of the user to force sign out. + @param error An optional out parameter for error results. + @return @YES when the sign out request was successful. @NO otherwise. + */ +- (BOOL)signOutByForceWithUserID:(NSString *)userID error:(NSError *_Nullable *_Nullable)error; + +/** @fn completeSignInWithTokenService:callback: + @brief Completes a sign-in flow once we have access and refresh tokens for the user. + @param accessToken The STS access token. + @param accessTokenExpirationDate The approximate expiration date of the access token. + @param refreshToken The STS refresh token. + @param anonymous Whether or not the user is anonymous. + @param callback Called when the user has been signed in or when an error occurred. Invoked + asynchronously on the global auth work queue in the future. +*/ +- (void)completeSignInWithAccessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(nullable NSString *)refreshToken + anonymous:(BOOL)anonymous + callback:(FIRAuthResultCallback)callback; + +/** @fn signInFlowAuthResultCallbackByDecoratingCallback: + @brief Creates a FIRAuthResultCallback block which wraps another FIRAuthResultCallback; trying + to update the current user before forwarding it's invocations along to a subject block + @param callback Called when the user has been updated or when an error has occurred. Invoked + asynchronously on the main thread in the future. + @return Returns a block that updates the current user. + @remarks Typically invoked as part of the complete sign-in flow. For any other uses please + consider alternative ways of updating the current user. +*/ +- (FIRAuthDataResultCallback)signInFlowAuthDataResultCallbackByDecoratingCallback: + (nullable FIRAuthDataResultCallback)callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailAuthProvider.m new file mode 100644 index 00000000..27bf16e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailAuthProvider.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIREmailAuthProvider + +- (instancetype)init { + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." + reason:@"This class is not meant to be initialized." + userInfo:nil]; +} + ++ (FIRAuthCredential *)credentialWithEmail:(NSString *)email password:(NSString *)password { + return [[FIREmailPasswordAuthCredential alloc] initWithEmail:email password:password]; +} + ++ (FIRAuthCredential *)credentialWithEmail:(NSString *)email link:(NSString *)link { + return [[FIREmailPasswordAuthCredential alloc] initWithEmail:email link:link]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h new file mode 100644 index 00000000..df683e6f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIREmailPasswordAuthCredential + @brief Internal implementation of FIRAuthCredential for Email/Password credentials. + */ +@interface FIREmailPasswordAuthCredential : FIRAuthCredential + +/** @property email + @brief The user's email address. + */ +@property(nonatomic, readonly) NSString *email; + +/** @property password + @brief The user's password. + */ +@property(nonatomic, readonly) NSString *password; + +/** @property link + @brief The email sign-in link. + */ +@property(nonatomic, readonly) NSString *link; + +/** @fn initWithEmail:password: + @brief Designated initializer. + @param email The user's email address. + @param password The user's password. + */ +- (nullable instancetype)initWithEmail:(NSString *)email + password:(NSString *)password NS_DESIGNATED_INITIALIZER; + +/** @fn initWithEmail:link: + @brief Designated initializer. + @param email The user's email address. + @param link The email sign-in link. + */ +- (nullable instancetype)initWithEmail:(NSString *)email + link:(NSString *)link NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.m new file mode 100644 index 00000000..d589e656 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.m @@ -0,0 +1,92 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIREmailPasswordAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIREmailPasswordAuthCredential + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithEmail:(NSString *)email password:(NSString *)password { + self = [super initWithProvider:FIREmailAuthProviderID]; + if (self) { + _email = [email copy]; + _password = [password copy]; + } + return self; +} + +- (nullable instancetype)initWithEmail:(NSString *)email link:(NSString *)link { + self = [super initWithProvider:FIREmailAuthProviderID]; + if (self) { + _email = [email copy]; + _link = [link copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason: + @"Attempt to call prepareVerifyAssertionRequest: on a FIREmailPasswordAuthCredential."]; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *email = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"email"]; + NSString *password = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"password"]; + NSString *link = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"link"]; + if (email.length && password.length) { + self = [self initWithEmail:email password:password]; + } else if (email.length && link.length) { + self = [self initWithEmail:email link:link]; + } else { + self = nil; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.email forKey:@"email"]; + [aCoder encodeObject:self.password forKey:@"password"]; + [aCoder encodeObject:self.link forKey:@"link"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential.m new file mode 100644 index 00000000..2f633f79 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential.m @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthCredential + +- (instancetype)init { + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." + reason:@"This class is an abstract base class. It's init method " + "should not be called directly." + userInfo:nil]; +} + +- (nullable instancetype)initWithProvider:(NSString *)provider { + self = [super init]; + if (self) { + _provider = [provider copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + @throw [NSException exceptionWithName:@"Attempt to call virtual method." + reason:@"This method must be overridden by a subclass." + userInfo:nil]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h new file mode 100644 index 00000000..82ecf4fa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRVerifyAssertionRequest; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthCredential () + +/** @fn initWithProvider: + @brief Designated initializer. + @remarks This is the designated initializer for internal/friend subclasses. + @param provider The provider name. + */ +- (nullable instancetype)initWithProvider:(NSString *)provider NS_DESIGNATED_INITIALIZER; + +/** @fn prepareVerifyAssertionRequest: + @brief Called immediately before a request to the verifyAssertion endpoint is made. Implementers + should update the passed request instance with their credentials. + @param request The request to be updated with credentials. + */ +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthProvider.m new file mode 100644 index 00000000..6192ad69 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/FIRAuthProvider.m @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#pragma mark - Provider ID constants + +// Declared 'extern' in FIRGoogleAuthProvider.h +NSString *const FIRGoogleAuthProviderID = @"google.com"; + +// Declared 'extern' in FIRFacebookAuthProvider.h +NSString *const FIRFacebookAuthProviderID = @"facebook.com"; + +// Declared 'extern' in FIREmailAuthProvider.h +NSString *const FIREmailAuthProviderID = @"password"; + +// Declared 'extern' in FIRTwitterAuthProvider.h +NSString *const FIRTwitterAuthProviderID = @"twitter.com"; + +// Declared 'extern' in FIRGitHubAuthProvider.h +NSString *const FIRGitHubAuthProviderID = @"github.com"; + +// Declared 'extern' in FIRPhoneAuthProvider.h +NSString *const FIRPhoneAuthProviderID = @"phone"; + +// Declared 'extern' in FIRGameCenterAuthProvider.h +NSString *const FIRGameCenterAuthProviderID = @"gc.apple.com"; + +#pragma mark - sign-in methods constants + +// Declared 'extern' in FIRGoogleAuthProvider.h +NSString *const FIRGoogleAuthSignInMethod = @"google.com"; + +// Declared 'extern' in FIREmailAuthProvider.h +NSString *const FIREmailPasswordAuthSignInMethod = @"password"; + +// Declared 'extern' in FIREmailAuthProvider.h +NSString *const FIREmailLinkAuthSignInMethod = @"emailLink"; + +// Declared 'extern' in FIRTwitterAuthProvider.h +NSString *const FIRTwitterAuthSignInMethod = @"twitter.com"; + +// Declared 'extern' in FIRFacebookAuthProvider.h +NSString *const FIRFacebookAuthSignInMethod = @"facebook.com"; + +// Declared 'extern' in FIRGitHubAuthProvider.h +NSString *const FIRGitHubAuthSignInMethod = @"github.com"; + +// Declared 'extern' in FIRPhoneAuthProvider.h +NSString *const FIRPhoneAuthSignInMethod = @"phone"; + +// Declared 'extern' in FIRGameCenterAuthProvider.h +NSString *const FIRGameCenterAuthSignInMethod = @"gc.apple.com"; diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h new file mode 100644 index 00000000..646ddba4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRFacebookAuthCredential + @brief Internal implementation of FIRAuthCredential for the Facebook IdP. + */ +@interface FIRFacebookAuthCredential : FIRAuthCredential + +/** @fn initWithAccessToken: + @brief Designated initializer. + @param accessToken The Access Token obtained from Facebook. + */ +- (nullable instancetype)initWithAccessToken:(NSString *)accessToken NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.m new file mode 100644 index 00000000..1f1adc4e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFacebookAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIRFacebookAuthCredential { + NSString *_accessToken; +} + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithAccessToken:(NSString *)accessToken { + self = [super initWithProvider:FIRFacebookAuthProviderID]; + if (self) { + _accessToken = [accessToken copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + request.providerAccessToken = _accessToken; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"accessToken"]; + self = [self initWithAccessToken:accessToken]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_accessToken forKey:@"accessToken"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthProvider.m new file mode 100644 index 00000000..83becf66 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthProvider.m @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +// FIRFacebookAuthProviderID is defined in FIRAuthProvider.m. + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRFacebookAuthProvider + +- (instancetype)init { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."]; + return nil; +} + ++ (FIRAuthCredential *)credentialWithAccessToken:(NSString *)accessToken { + return [[FIRFacebookAuthCredential alloc] initWithAccessToken:accessToken]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h new file mode 100644 index 00000000..3272c5aa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGameCenterAuthCredential + @brief Internal implementation of FIRAuthCredential for Game Center credentials. + */ +@interface FIRGameCenterAuthCredential : FIRAuthCredential + +/** @property playerID + @brief The ID of the Game Center local player. + */ +@property(nonatomic, readonly) NSString *playerID; + +/** @property publicKeyURL + @brief The URL for the public encryption key. + */ +@property(nonatomic, readonly) NSURL *publicKeyURL; + +/** @property signature + @brief The verification signature data generated. + */ +@property(nonatomic, readonly) NSData *signature; + +/** @property salt + @brief A random string used to compute the hash and keep it randomized. + */ +@property(nonatomic, readonly) NSData *salt; + +/** @property timestamp + @brief The date and time that the signature was created. + */ +@property(nonatomic, readonly) uint64_t timestamp; + +/** @property displayName + @brief The date and time that the signature was created. + */ +@property(nonatomic, readonly) NSString *displayName; + +/** @fn initWithPlayerID:publicKeyURL:signature:salt:timestamp:displayName: + @brief Designated initializer. + @param publicKeyURL The URL for the public encryption key. + @param signature The verification signature generated. + @param salt A random string used to compute the hash and keep it randomized. + @param timestamp The date and time that the signature was created. + */ +- (nullable instancetype)initWithPlayerID:(NSString *)playerID + publicKeyURL:(NSURL *)publicKeyURL + signature:(NSData *)signature + salt:(NSData *)salt + timestamp:(uint64_t)timestamp + displayName:(NSString *)displayName NS_DESIGNATED_INITIALIZER; + +/** @fn initWithProvider: + @brief Initializer with a provider name. + @param provider The provider name. + */ +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.m new file mode 100644 index 00000000..132eafe5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.m @@ -0,0 +1,92 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRGameCenterAuthCredential + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithPlayerID:(NSString *)playerID + publicKeyURL:(NSURL *)publicKeyURL + signature:(NSData *)signature + salt:(NSData *)salt + timestamp:(uint64_t)timestamp + displayName:(NSString *)displayName { + self = [super initWithProvider:FIRGameCenterAuthProviderID]; + if (self) { + _playerID = [playerID copy]; + _publicKeyURL = [publicKeyURL copy]; + _signature = [signature copy]; + _salt = [salt copy]; + _timestamp = timestamp; + _displayName = [displayName copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason: + @"Attempt to call prepareVerifyAssertionRequest: on a FIRGameCenterAuthCredential."]; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *playerID = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"playerID"]; + NSURL *publicKeyURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:@"publicKeyURL"]; + NSData *signature = [aDecoder decodeObjectOfClass:[NSData class] forKey:@"signature"]; + NSData *salt = [aDecoder decodeObjectOfClass:[NSData class] forKey:@"salt"]; + NSNumber *timestamp = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:@"timestamp"]; + NSString *displayName = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"displayName"]; + self = [self initWithPlayerID:playerID + publicKeyURL:publicKeyURL + signature:signature + salt:salt + timestamp:timestamp.unsignedLongLongValue + displayName:displayName]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.playerID forKey:@"playerID"]; + [aCoder encodeObject:self.publicKeyURL forKey:@"publicKeyURL"]; + [aCoder encodeObject:self.signature forKey:@"signature"]; + [aCoder encodeObject:self.salt forKey:@"salt"]; + [aCoder encodeObject:[NSNumber numberWithUnsignedLongLong:self.timestamp] forKey:@"timestamp"]; + [aCoder encodeObject:self.displayName forKey:@"displayName"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthProvider.m new file mode 100644 index 00000000..d2daef40 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthProvider.m @@ -0,0 +1,92 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRGameCenterAuthProvider + +- (instancetype)init { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."]; + return nil; +} + ++ (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion { + /** + Linking GameKit.framework without using it on macOS results in App Store rejection. + Thus we don't link GameKit.framework to our SDK directly. `optionalLocalPlayer` is used for + checking whether the APP that consuming our SDK has linked GameKit.framework. If not, a + `GameKitNotLinkedError` will be raised. + **/ + GKLocalPlayer *_Nullable optionalLocalPlayer = [[NSClassFromString(@"GKLocalPlayer") alloc] init]; + + if (!optionalLocalPlayer) { + if (completion) { + completion(nil, [FIRAuthErrorUtils gameKitNotLinkedError]); + } + return; + } + + __weak GKLocalPlayer *localPlayer = [[optionalLocalPlayer class] localPlayer]; + if (!localPlayer.isAuthenticated) { + if (completion) { + completion(nil, [FIRAuthErrorUtils localPlayerNotAuthenticatedError]); + } + return; + } + + [localPlayer generateIdentityVerificationSignatureWithCompletionHandler:^( + NSURL *publicKeyURL, NSData *signature, NSData *salt, uint64_t timestamp, + NSError *error) { + if (error) { + if (completion) { + completion(nil, error); + } + } else { + if (completion) { + /** + @c `localPlayer.alias` is actually the displayname needed, instead of + `localPlayer.displayname`. For more information, check + https://developer.apple.com/documentation/gamekit/gkplayer + **/ + NSString *displayName = localPlayer.alias; +// iOS 13 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + FIRGameCenterAuthCredential *credential = + [[FIRGameCenterAuthCredential alloc] initWithPlayerID:localPlayer.playerID + publicKeyURL:publicKeyURL + signature:signature + salt:salt + timestamp:timestamp + displayName:displayName]; +#pragma clang diagnostic pop + completion(credential, nil); + } + } + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h new file mode 100644 index 00000000..f6765c41 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGitHubAuthCredential + @brief Internal implementation of FIRAuthCredential for GitHub credentials. + */ +@interface FIRGitHubAuthCredential : FIRAuthCredential + +/** @property token + @brief The GitHub OAuth access token. + */ +@property(nonatomic, readonly) NSString *token; + +/** @fn initWithToken: + @brief Designated initializer. + @param token The GitHub OAuth access token. + */ +- (nullable instancetype)initWithToken:(NSString *)token NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.m new file mode 100644 index 00000000..ce9dbf13 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.m @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRGitHubAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIRGitHubAuthCredential + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithToken:(NSString *)token { + self = [super initWithProvider:FIRGitHubAuthProviderID]; + if (self) { + _token = [token copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + request.providerAccessToken = _token; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *token = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"token"]; + self = [self initWithToken:token]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.token forKey:@"token"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthProvider.m new file mode 100644 index 00000000..6c448e1e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthProvider.m @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +// FIRGitHubAuthProviderID is defined in FIRAuthProvider.m. + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRGitHubAuthProvider + +- (instancetype)init { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."]; + return nil; +} + ++ (FIRAuthCredential *)credentialWithToken:(NSString *)token { + return [[FIRGitHubAuthCredential alloc] initWithToken:token]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h new file mode 100644 index 00000000..6d205c10 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGoogleAuthCredential + @brief Internal implementation of FIRAuthCredential for the Google IdP. + */ +@interface FIRGoogleAuthCredential : FIRAuthCredential + +/** @fn initWithIDToken:accessToken: + @brief Designated initializer. + @param IDToken The ID Token obtained from Google. + @param accessToken The Access Token obtained from Google. + */ +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + accessToken:(NSString *)accessToken NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.m new file mode 100644 index 00000000..36b8b5c5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.m @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRGoogleAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIRGoogleAuthCredential { + NSString *_IDToken; + NSString *_accessToken; +} + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken accessToken:(NSString *)accessToken { + self = [super initWithProvider:FIRGoogleAuthProviderID]; + if (self) { + _IDToken = [IDToken copy]; + _accessToken = [accessToken copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + request.providerIDToken = _IDToken; + request.providerAccessToken = _accessToken; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *IDToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"IDToken"]; + NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"accessToken"]; + self = [self initWithIDToken:IDToken accessToken:accessToken]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_IDToken forKey:@"IDToken"]; + [aCoder encodeObject:_accessToken forKey:@"accessToken"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthProvider.m new file mode 100644 index 00000000..ce234bc7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthProvider.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +// FIRGoogleAuthProviderID is defined in FIRAuthProvider.m. + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRGoogleAuthProvider + +- (instancetype)init { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."]; + return nil; +} + ++ (FIRAuthCredential *)credentialWithIDToken:(NSString *)IDToken + accessToken:(NSString *)accessToken { + return [[FIRGoogleAuthCredential alloc] initWithIDToken:IDToken accessToken:accessToken]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential.m new file mode 100644 index 00000000..99a118fa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential.m @@ -0,0 +1,130 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIROAuthCredential () + +@property(nonatomic, nullable) NSString *rawNonce; + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIROAuthCredential + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (instancetype)initWithProviderID:(NSString *)providerID + IDToken:(nullable NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce + accessToken:(nullable NSString *)accessToken + secret:(nullable NSString *)secret + pendingToken:(nullable NSString *)pendingToken { + self = [super initWithProvider:providerID]; + if (self) { + _IDToken = IDToken; + _rawNonce = rawNonce; + _accessToken = accessToken; + _pendingToken = pendingToken; + _secret = secret; + } + return self; +} + +- (instancetype)initWithProviderID:(NSString *)providerID + sessionID:(NSString *)sessionID + OAuthResponseURLString:(NSString *)OAuthResponseURLString { + self = [self initWithProviderID:providerID + IDToken:nil + rawNonce:nil + accessToken:nil + secret:nil + pendingToken:nil]; + if (self) { + _OAuthResponseURLString = OAuthResponseURLString; + _sessionID = sessionID; + } + return self; +} + +- (nullable instancetype)initWithVerifyAssertionResponse:(FIRVerifyAssertionResponse *)response { + if (response.oauthIDToken.length || response.oauthAccessToken.length || + response.oauthSecretToken.length) { + return [self initWithProviderID:response.providerID + IDToken:response.oauthIDToken + rawNonce:nil + accessToken:response.oauthAccessToken + secret:response.oauthSecretToken + pendingToken:response.pendingToken]; + } + return nil; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + request.providerIDToken = _IDToken; + request.providerRawNonce = _rawNonce; + request.providerAccessToken = _accessToken; + request.requestURI = _OAuthResponseURLString; + request.sessionID = _sessionID; + request.providerOAuthTokenSecret = _secret; + request.pendingToken = _pendingToken; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *IDToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"IDToken"]; + NSString *rawNonce = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"rawNonce"]; + NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"accessToken"]; + NSString *pendingToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"pendingToken"]; + NSString *secret = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"secret"]; + self = [self initWithProviderID:self.provider + IDToken:IDToken + rawNonce:rawNonce + accessToken:accessToken + secret:secret + pendingToken:pendingToken]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.IDToken forKey:@"IDToken"]; + [aCoder encodeObject:self.rawNonce forKey:@"rawNonce"]; + [aCoder encodeObject:self.accessToken forKey:@"accessToken"]; + [aCoder encodeObject:self.pendingToken forKey:@"pendingToken"]; + [aCoder encodeObject:self.secret forKey:@"secret"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h new file mode 100644 index 00000000..9f2c459f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRVerifyAssertionResponse; + +NS_ASSUME_NONNULL_BEGIN + +/** @extension FIROAuthCredential + @brief Internal implementation of FIRAuthCredential for generic credentials. + */ +@interface FIROAuthCredential () + +/** @property OAuthResponseURLString + @brief A string representation of the response URL corresponding to this OAuthCredential. + */ +@property(nonatomic, readonly, nullable) NSString *OAuthResponseURLString; + +/** @property sessionID + @brief The session ID used when completing the headful-lite flow. + */ +@property(nonatomic, readonly, nullable) NSString *sessionID; + +/** @property pendingToken + @brief The pending token used when completing the headful-lite flow. + */ +@property(nonatomic, readonly, nullable) NSString *pendingToken; + +/** @fn initWithProviderId:IDToken:accessToken:secret:pendingToken + @brief Designated initializer. + @param providerID The provider ID associated with the credential being created. + @param IDToken The ID Token associated with the credential being created. + @param rawNonce The raw nonce associated with the Auth credential being created. + @param accessToken The access token associated with the credential being created. + @param secret The secret associated with the credential being created. + @param pendingToken The pending token associated with the credential being created. + */ +- (instancetype)initWithProviderID:(NSString *)providerID + IDToken:(nullable NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce + accessToken:(nullable NSString *)accessToken + secret:(nullable NSString *)secret + pendingToken:(nullable NSString *)pendingToken NS_DESIGNATED_INITIALIZER; + +/** @fn initWithProviderId:sessionID:OAuthResponseURLString: + @brief Intitializer which takes a sessionID and an OAuthResponseURLString. + @param providerID The provider ID associated with the credential being created. + @param sessionID The session ID used when completing the headful-lite flow. + @param OAuthResponseURLString The error that occurred if any. + */ +- (instancetype)initWithProviderID:(NSString *)providerID + sessionID:(NSString *)sessionID + OAuthResponseURLString:(NSString *)OAuthResponseURLString; + +/** @fn initWithVerifyAssertionResponse + @brief Intitializer which takes an verifyAssertion response. + @param response The verifyAssertion Response to create the credential instance. + */ +- (nullable instancetype)initWithVerifyAssertionResponse:(FIRVerifyAssertionResponse *)response; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthProvider.m new file mode 100644 index 00000000..348fb57b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthProvider.m @@ -0,0 +1,400 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#import +#import +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h" + +#if TARGET_OS_IOS +#import "FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRHeadfulLiteURLCallBack + @brief The callback invoked at the end of the flow to fetch a headful-lite URL. + @param headfulLiteURL The headful lite URL. + @param error The error that occurred while fetching the headful-lite, if any. + */ +typedef void (^FIRHeadfulLiteURLCallBack)(NSURL *_Nullable headfulLiteURL, + NSError *_Nullable error); + +/** @var kHeadfulLiteURLStringFormat + @brief The format of the URL used to open the headful lite page during sign-in. + */ +NSString *const kHeadfulLiteURLStringFormat = @"https://%@/__/auth/handler?%@"; + +/** @var kauthTypeSignInWithRedirect + @brief The auth type to be specified in the sign-in request with redirect request and response. + */ +static NSString *const kAuthTypeSignInWithRedirect = @"signInWithRedirect"; + +@implementation FIROAuthProvider { + /** @var _auth + @brief The auth instance used for launching the URL presenter. + */ + FIRAuth *_auth; + + /** @var _callbackScheme + @brief The callback URL scheme used for headful-lite sign-in. + */ + NSString *_callbackScheme; +} + ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + accessToken:(nullable NSString *)accessToken { + return [[FIROAuthCredential alloc] initWithProviderID:providerID + IDToken:IDToken + rawNonce:nil + accessToken:accessToken + secret:nil + pendingToken:nil]; +} + ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + accessToken:(NSString *)accessToken { + return [[FIROAuthCredential alloc] initWithProviderID:providerID + IDToken:nil + rawNonce:nil + accessToken:accessToken + secret:nil + pendingToken:nil]; +} + ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce + accessToken:(nullable NSString *)accessToken { + return [[FIROAuthCredential alloc] initWithProviderID:providerID + IDToken:IDToken + rawNonce:rawNonce + accessToken:accessToken + secret:nil + pendingToken:nil]; +} + ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce { + return [[FIROAuthCredential alloc] initWithProviderID:providerID + IDToken:IDToken + rawNonce:rawNonce + accessToken:nil + secret:nil + pendingToken:nil]; +} + ++ (instancetype)providerWithProviderID:(NSString *)providerID { + return [[self alloc] initWithProviderID:providerID auth:[FIRAuth auth]]; +} + ++ (instancetype)providerWithProviderID:(NSString *)providerID auth:(FIRAuth *)auth { + return [[self alloc] initWithProviderID:providerID auth:auth]; +} + +#if TARGET_OS_IOS +- (void)getCredentialWithUIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthCredentialCallback)completion { + if (![FIRAuthWebUtils isCallbackSchemeRegisteredForCustomURLScheme:self->_callbackScheme]) { + [NSException raise:NSInternalInconsistencyException + format:@"Please register custom URL scheme '%@' in the app's Info.plist file.", + self->_callbackScheme]; + } + __weak __typeof__(self) weakSelf = self; + __weak FIRAuth *weakAuth = _auth; + __weak NSString *weakProviderID = _providerID; + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRAuthCredentialCallback callbackOnMainThread = + ^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(credential, error); + }); + } + }; + NSString *eventID = [FIRAuthWebUtils randomStringWithLength:10]; + NSString *sessionID = [FIRAuthWebUtils randomStringWithLength:10]; + __strong __typeof__(self) strongSelf = weakSelf; + [strongSelf + getHeadFulLiteURLWithEventID:eventID + sessionID:sessionID + completion:^(NSURL *_Nullable headfulLiteURL, NSError *_Nullable error) { + if (error) { + callbackOnMainThread(nil, error); + return; + } + FIRAuthURLCallbackMatcher callbackMatcher = + ^BOOL(NSURL *_Nullable callbackURL) { + return [FIRAuthWebUtils + isExpectedCallbackURL:callbackURL + eventID:eventID + authType:kAuthTypeSignInWithRedirect + callbackScheme:strongSelf->_callbackScheme]; + }; + __strong FIRAuth *strongAuth = weakAuth; + [strongAuth.authURLPresenter + presentURL:headfulLiteURL + UIDelegate:UIDelegate + callbackMatcher:callbackMatcher + completion:^(NSURL *_Nullable callbackURL, + NSError *_Nullable error) { + if (error) { + callbackOnMainThread(nil, error); + return; + } + NSString *OAuthResponseURLString = + [strongSelf OAuthResponseForURL:callbackURL + error:&error]; + if (error) { + callbackOnMainThread(nil, error); + return; + } + __strong NSString *strongProviderID = weakProviderID; + FIROAuthCredential *credential = [[FIROAuthCredential alloc] + initWithProviderID:strongProviderID + sessionID:sessionID + OAuthResponseURLString:OAuthResponseURLString]; + callbackOnMainThread(credential, nil); + }]; + }]; + }); +} +#endif // TARGET_OS_IOS + +#pragma mark - Internal Methods + +/** @fn initWithProviderID:auth: + @brief returns an instance of @c FIROAuthProvider associated with the provided auth instance. + @param auth The Auth instance to be associated with the OAuthProvider instance. + @return An Instance of @c FIROAuthProvider. + */ +- (nullable instancetype)initWithProviderID:(NSString *)providerID auth:(FIRAuth *)auth { + NSAssert(![providerID isEqual:FIRFacebookAuthProviderID], + @"Sign in with Facebook is not supported via generic IDP; the Facebook TOS " + "dictate that you must use the Facebook iOS SDK for Facebook login."); + NSAssert(![providerID isEqual:@"apple.com"], + @"Sign in with Apple is not supported via generic IDP; You must use the Apple iOS SDK" + " for Sign in with Apple."); + self = [super init]; + if (self) { + _auth = auth; + _providerID = providerID; + _callbackScheme = [[[_auth.app.options.clientID componentsSeparatedByString:@"."] + reverseObjectEnumerator].allObjects componentsJoinedByString:@"."]; + } + return self; +} + +/** @fn OAuthResponseForURL:error: + @brief Parses the redirected URL and returns a string representation of the OAuth response URL. + @param URL The url to be parsed for an OAuth response URL. + @param error The error that occurred if any. + @return The OAuth response if successful. + */ +- (nullable NSString *)OAuthResponseForURL:(NSURL *)URL error:(NSError *_Nullable *_Nullable)error { + NSDictionary *URLQueryItems = + [FIRAuthWebUtils dictionaryWithHttpArgumentsString:URL.query]; + NSURL *deepLinkURL = [NSURL URLWithString:URLQueryItems[@"deep_link_id"]]; + URLQueryItems = [FIRAuthWebUtils dictionaryWithHttpArgumentsString:deepLinkURL.query]; + NSString *queryItemLink = URLQueryItems[@"link"]; + if (queryItemLink) { + return queryItemLink; + } + if (!error) { + return nil; + } + NSData *errorData = [URLQueryItems[@"firebaseError"] dataUsingEncoding:NSUTF8StringEncoding]; + NSError *jsonError; + NSDictionary *errorDict = [NSJSONSerialization JSONObjectWithData:errorData + options:0 + error:&jsonError]; + if (jsonError) { + *error = [FIRAuthErrorUtils JSONSerializationErrorWithUnderlyingError:jsonError]; + return nil; + } + *error = [FIRAuthErrorUtils URLResponseErrorWithCode:errorDict[@"code"] + message:errorDict[@"message"]]; + if (!*error) { + NSString *reason; + if (errorDict[@"code"] && errorDict[@"message"]) { + reason = [NSString stringWithFormat:@"[%@] - %@", errorDict[@"code"], errorDict[@"message"]]; + } + *error = [FIRAuthErrorUtils webSignInUserInteractionFailureWithReason:reason]; + } + return nil; +} + +/** @fn getHeadFulLiteURLWithEventID:completion: + @brief Constructs a URL used for opening a headful-lite flow using a given event + ID and session ID. + @param eventID The event ID used for this purpose. + @param sessionID The session ID used when completing the headful lite flow. + @param completion The callback invoked after the URL has been constructed or an error + has been encountered. + */ +- (void)getHeadFulLiteURLWithEventID:(NSString *)eventID + sessionID:(NSString *)sessionID + completion:(FIRHeadfulLiteURLCallBack)completion { + __weak __typeof__(self) weakSelf = self; + [FIRAuthWebUtils + fetchAuthDomainWithRequestConfiguration:_auth.requestConfiguration + completion:^(NSString *_Nullable authDomain, + NSError *_Nullable error) { + if (error) { + if (completion) { + completion(nil, error); + } + return; + } + __strong __typeof__(self) strongSelf = weakSelf; + NSString *bundleID = [NSBundle mainBundle].bundleIdentifier; + NSString *clienID = strongSelf->_auth.app.options.clientID; + NSString *apiKey = + strongSelf->_auth.requestConfiguration.APIKey; + NSMutableDictionary *urlArguments = [@{ + @"apiKey" : apiKey, + @"authType" : @"signInWithRedirect", + @"ibi" : bundleID ?: @"", + @"clientId" : clienID, + @"sessionId" : [strongSelf hashforString:sessionID], + @"v" : [FIRAuthBackend authUserAgent], + @"eventId" : eventID, + @"providerId" : strongSelf->_providerID, + } mutableCopy]; + if (strongSelf.scopes.count) { + urlArguments[@"scopes"] = + [strongSelf.scopes componentsJoinedByString:@","]; + } + if (strongSelf.customParameters.count) { + NSString *customParameters = + [strongSelf customParametersStringWithError:&error]; + if (error) { + completion(nil, error); + return; + } + if (customParameters) { + urlArguments[@"customParameters"] = customParameters; + } + } + if (strongSelf->_auth.requestConfiguration.languageCode) { + urlArguments[@"hl"] = + strongSelf->_auth.requestConfiguration.languageCode; + } + NSString *argumentsString = [strongSelf + httpArgumentsStringForArgsDictionary:urlArguments]; + NSString *URLString = + [NSString stringWithFormat:kHeadfulLiteURLStringFormat, + authDomain, argumentsString]; + if (completion) { + NSCharacterSet *set = + [NSCharacterSet URLFragmentAllowedCharacterSet]; + completion( + [NSURL + URLWithString: + [URLString + stringByAddingPercentEncodingWithAllowedCharacters: + set]], + nil); + } + }]; +} + +/** @fn customParametersString + @brief Returns a JSON string representation of the custom parameters dictionary corresponding + to the OAuthProvider. + @return The JSON string representation of the custom parameters dictionary corresponding + to the OAuthProvider. + */ +- (nullable NSString *)customParametersStringWithError:(NSError *_Nullable *_Nullable)error { + if (!_customParameters.count) { + return nil; + } + + if (!error) { + return nil; + } + NSError *jsonError; + NSData *customParametersJSONData = [NSJSONSerialization dataWithJSONObject:_customParameters + options:0 + error:&jsonError]; + if (jsonError) { + *error = [FIRAuthErrorUtils JSONSerializationErrorWithUnderlyingError:jsonError]; + return nil; + } + + NSString *customParamsRawJSON = [[NSString alloc] initWithData:customParametersJSONData + encoding:NSUTF8StringEncoding]; + return customParamsRawJSON; +} + +/** @fn hashforString: + @brief Returns the SHA256 hash representation of a given string object. + @param string The string for which a SHA256 hash is desired. + @return An hexadecimal string representation of the SHA256 hash. + */ +- (NSString *)hashforString:(NSString *)string { + NSData *sessionIDData = [string dataUsingEncoding:NSUTF8StringEncoding]; + NSMutableData *hashOutputData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; + if (CC_SHA256(sessionIDData.bytes, (CC_LONG)[sessionIDData length], + hashOutputData.mutableBytes)) { + } + return [self hexStringFromData:hashOutputData]; + ; +} + +/** @fn hexStringFromData: + @brief Returns the hexadecimal string representation of an NSData object. + @param data The NSData object for which a hexadecical string is desired. + @return The hexadecimal string representation of the supplied NSData object. + */ +- (NSString *)hexStringFromData:(NSData *)data { + const unsigned char *dataBuffer = (const unsigned char *)[data bytes]; + NSMutableString *string = [[NSMutableString alloc] init]; + for (unsigned int i = 0; i < data.length; i++) { + [string appendFormat:@"%02lx", (unsigned long)dataBuffer[i]]; + } + return [string copy]; +} + +- (NSString *)httpArgumentsStringForArgsDictionary:(NSDictionary *)argsDictionary { + NSMutableArray *arguments = [NSMutableArray arrayWithCapacity:argsDictionary.count]; + NSString *key; + for (key in argsDictionary) { + NSString *description = [argsDictionary[key] description]; + [arguments + addObject:[NSString + stringWithFormat:@"%@=%@", + [FIRAuthWebUtils stringByUnescapingFromURLArgument:key], + [FIRAuthWebUtils + stringByUnescapingFromURLArgument:description]]]; + } + return [arguments componentsJoinedByString:@"&"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential.m new file mode 100644 index 00000000..0444adfc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential.m @@ -0,0 +1,107 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +#if TARGET_OS_IOS +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRPhoneAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIRPhoneAuthCredential + +- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof + phoneNumber:(NSString *)phoneNumber + providerID:(NSString *)providerID { + self = [super initWithProvider:providerID]; + if (self) { + _temporaryProof = [temporaryProof copy]; + _phoneNumber = [phoneNumber copy]; + } + return self; +} + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (instancetype)initWithProviderID:(NSString *)providerID + verificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode { + self = [super initWithProvider:providerID]; + if (self) { + _verificationID = [verificationID copy]; + _verificationCode = [verificationCode copy]; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *verificationID = [aDecoder decodeObjectOfClass:[NSString class] + forKey:@"verificationID"]; + NSString *verificationCode = [aDecoder decodeObjectOfClass:[NSString class] + forKey:@"verificationCode"]; + NSString *temporaryProof = [aDecoder decodeObjectOfClass:[NSString class] + forKey:@"temporaryProof"]; + NSString *phoneNumber = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"phoneNumber"]; + if (temporaryProof.length && phoneNumber.length) { + self = [self initWithTemporaryProof:temporaryProof + phoneNumber:phoneNumber + providerID:self.provider]; + } else if (verificationID.length && verificationCode.length) { + self = [self initWithProviderID:self.provider + verificationID:verificationID + verificationCode:verificationCode]; + } else { + self = nil; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.verificationID forKey:@"verificationID"]; + [aCoder encodeObject:self.verificationCode forKey:@"verificationCode"]; + [aCoder encodeObject:self.temporaryProof forKey:@"temporaryProof"]; + [aCoder encodeObject:self.phoneNumber forKey:@"phoneNumber"]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h new file mode 100644 index 00000000..709ccfc6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @extension FIRPhoneAuthCredential + @brief Internal implementation of FIRAuthCredential for Phone Auth credentials. + */ +@interface FIRPhoneAuthCredential () + +/** @var verificationID + @brief The verification ID obtained from invoking @c verifyPhoneNumber:completion: + */ +@property(nonatomic, readonly, nonnull) NSString *verificationID; + +/** @var verificationCode + @brief The verification code provided by the user. + */ +@property(nonatomic, readonly, nonnull) NSString *verificationCode; + +/** @var temporaryProof + @brief The a temporary proof code perftaining to this credential, returned from the backend. + */ +@property(nonatomic, readonly, nonnull) NSString *temporaryProof; + +/** @var phoneNumber + @brief The a phone number pertaining to this credential, returned from the backend. + */ +@property(nonatomic, readonly, nonnull) NSString *phoneNumber; + +/** @var initWithTemporaryProof:phoneNumber: + @brief Designated Initializer. + @param providerID The provider ID associated with the phone auth credential being created. + */ +- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof + phoneNumber:(NSString *)phoneNumber + providerID:(NSString *)providerID NS_DESIGNATED_INITIALIZER; + +/** @var initWithProviderID:verificationID:verificationCode: + @brief Designated Initializer. + @param providerID The provider ID associated with the phone auth credential being created. + @param verificationID The verification ID associated witht Phone Auth credential being created. + @param verificationCode The verification code associated witht Phone Auth credential being + created. + */ +- (instancetype)initWithProviderID:(NSString *)providerID + verificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthProvider.m new file mode 100644 index 00000000..e0ddf86b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthProvider.m @@ -0,0 +1,716 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import +#import +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h" + +#if TARGET_OS_IOS +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRReCAPTCHAURLCallBack + @brief The callback invoked at the end of the flow to fetch a reCAPTCHA URL. + @param reCAPTCHAURL The reCAPTCHA URL. + @param error The error that occurred while fetching the reCAPTCHAURL, if any. + */ +typedef void (^FIRReCAPTCHAURLCallBack)(NSURL *_Nullable reCAPTCHAURL, NSError *_Nullable error); + +/** @typedef FIRVerifyClientCallback + @brief The callback invoked at the end of a client verification flow. + @param appCredential credential that proves the identity of the app during a phone + authentication flow. + @param error The error that occurred while verifying the app, if any. + */ +typedef void (^FIRVerifyClientCallback)(FIRAuthAppCredential *_Nullable appCredential, + NSString *_Nullable reCAPTCHAToken, + NSError *_Nullable error); + +/** @typedef FIRFetchAuthDomainCallback + @brief The callback invoked at the end of the flow to fetch the Auth domain. + @param authDomain The Auth domain. + @param error The error that occurred while fetching the auth domain, if any. + */ +typedef void (^FIRFetchAuthDomainCallback)(NSString *_Nullable authDomain, + NSError *_Nullable error); + +/** @var kauthTypeVerifyApp + @brief The auth type to be specified in the app verification request. + */ +static NSString *const kAuthTypeVerifyApp = @"verifyApp"; + +/** @var kReCAPTCHAURLStringFormat + @brief The format of the URL used to open the reCAPTCHA page during app verification. + */ +NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?"; + +extern NSString *const FIRPhoneMultiFactorID; + +@implementation FIRPhoneAuthProvider { + /** @var _auth + @brief The auth instance used for verifying the phone number. + */ + FIRAuth *_auth; + + /** @var _callbackScheme + @brief The callback URL scheme used for reCAPTCHA fallback. + */ + NSString *_callbackScheme; +} + +/** @fn initWithAuth: + @brief returns an instance of @c FIRPhoneAuthProvider associated with the provided auth + instance. + @return An Instance of @c FIRPhoneAuthProvider. + */ +- (nullable instancetype)initWithAuth:(FIRAuth *)auth { + self = [super init]; + if (self) { + _auth = auth; + _callbackScheme = [[[_auth.app.options.clientID componentsSeparatedByString:@"."] + reverseObjectEnumerator].allObjects componentsJoinedByString:@"."]; + } + return self; +} + +- (void)verifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRVerificationResultCallback)completion { + if (![FIRAuthWebUtils isCallbackSchemeRegisteredForCustomURLScheme:_callbackScheme]) { + [NSException raise:NSInternalInconsistencyException + format:@"Please register custom URL scheme '%@' in the app's Info.plist file.", + _callbackScheme]; + } + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRVerificationResultCallback callBackOnMainThread = + ^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(verificationID, error); + }); + } + }; + [self + internalVerifyPhoneNumber:phoneNumber + UIDelegate:UIDelegate + completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (!error) { + callBackOnMainThread(verificationID, nil); + return; + } else { + callBackOnMainThread(nil, error); + return; + } + }]; + }); +} + +- (void)verifyPhoneNumberWithMultiFactorInfo:(FIRPhoneMultiFactorInfo *)phoneMultiFactorInfo + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + completion:(nullable FIRVerificationResultCallback)completion { + session.multiFactorInfo = phoneMultiFactorInfo; + [self verifyPhoneNumber:phoneMultiFactorInfo.phoneNumber + UIDelegate:UIDelegate + multiFactorSession:session + completion:completion]; +} + +- (void)verifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + completion:(nullable FIRVerificationResultCallback)completion { + if (!session) { + [self verifyPhoneNumber:phoneNumber UIDelegate:UIDelegate completion:completion]; + return; + } + + if (![FIRAuthWebUtils isCallbackSchemeRegisteredForCustomURLScheme:_callbackScheme]) { + [NSException raise:NSInternalInconsistencyException + format:@"Please register custom URL scheme '%@' in the app's Info.plist file.", + _callbackScheme]; + } + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + FIRVerificationResultCallback callBackOnMainThread = + ^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(verificationID, error); + }); + } + }; + [self + internalVerifyPhoneNumber:phoneNumber + UIDelegate:UIDelegate + multiFactorSession:session + completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (!error) { + callBackOnMainThread(verificationID, nil); + return; + } else { + callBackOnMainThread(nil, error); + return; + } + }]; + }); +} + +- (FIRPhoneAuthCredential *)credentialWithVerificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode { + return [[FIRPhoneAuthCredential alloc] initWithProviderID:FIRPhoneAuthProviderID + verificationID:verificationID + verificationCode:verificationCode]; +} + ++ (instancetype)provider { + return [[self alloc] initWithAuth:[FIRAuth auth]]; +} + ++ (instancetype)providerWithAuth:(FIRAuth *)auth { + return [[self alloc] initWithAuth:auth]; +} + +#pragma mark - Internal Methods + +/** @fn reCAPTCHATokenForURL:error: + @brief Parses the reCAPTCHA URL and returns the reCAPTCHA token. + @param URL The url to be parsed for a reCAPTCHA token. + @param error The error that occurred if any. + @return The reCAPTCHA token if successful. + */ +- (NSString *)reCAPTCHATokenForURL:(NSURL *)URL error:(NSError **)error { + NSURLComponents *actualURLComponents = [NSURLComponents componentsWithURL:URL + resolvingAgainstBaseURL:NO]; + NSArray *queryItems = [actualURLComponents queryItems]; + NSString *deepLinkURL = [FIRAuthWebUtils queryItemValue:@"deep_link_id" from:queryItems]; + NSData *errorData; + if (deepLinkURL) { + actualURLComponents = [NSURLComponents componentsWithString:deepLinkURL]; + queryItems = [actualURLComponents queryItems]; + NSString *recaptchaToken = [FIRAuthWebUtils queryItemValue:@"recaptchaToken" from:queryItems]; + if (recaptchaToken) { + return recaptchaToken; + } + NSString *firebaseError = [FIRAuthWebUtils queryItemValue:@"firebaseError" from:queryItems]; + errorData = [firebaseError dataUsingEncoding:NSUTF8StringEncoding]; + } else { + errorData = nil; + } + NSError *jsonError; + NSDictionary *errorDict = [NSJSONSerialization JSONObjectWithData:errorData + options:0 + error:&jsonError]; + if (jsonError) { + *error = [FIRAuthErrorUtils JSONSerializationErrorWithUnderlyingError:jsonError]; + return nil; + } + *error = [FIRAuthErrorUtils URLResponseErrorWithCode:errorDict[@"code"] + message:errorDict[@"message"]]; + if (!*error) { + NSString *reason; + if (errorDict[@"code"] && errorDict[@"message"]) { + reason = [NSString stringWithFormat:@"[%@] - %@", errorDict[@"code"], errorDict[@"message"]]; + } else { + reason = [NSString stringWithFormat:@"An unknown error occurred with the following " + "response: %@", + deepLinkURL]; + } + *error = [FIRAuthErrorUtils appVerificationUserInteractionFailureWithReason:reason]; + } + return nil; +} + +/** @fn internalVerifyPhoneNumber:completion: + @brief Starts the phone number authentication flow by sending a verifcation code to the + specified phone number. + @param phoneNumber The phone number to be verified. + @param completion The callback to be invoked when the verification flow is finished. + */ + +- (void)internalVerifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRVerificationResultCallback)completion { + if (!phoneNumber.length) { + completion(nil, [FIRAuthErrorUtils missingPhoneNumberErrorWithMessage:nil]); + return; + } + [_auth.notificationManager + checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) { + if (!isNotificationBeingForwarded) { + completion(nil, [FIRAuthErrorUtils notificationNotForwardedError]); + return; + } + FIRVerificationResultCallback callback = + ^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (completion) { + completion(verificationID, error); + } + }; + [self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber + retryOnInvalidAppCredential:YES + UIDelegate:UIDelegate + callback:callback]; + }]; +} + +- (void)internalVerifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + completion:(nullable FIRVerificationResultCallback)completion { + if (!phoneNumber.length) { + if (completion) { + completion(nil, [FIRAuthErrorUtils missingPhoneNumberErrorWithMessage:nil]); + } + return; + } + [_auth.notificationManager + checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) { + if (!isNotificationBeingForwarded) { + if (completion) { + completion(nil, [FIRAuthErrorUtils notificationNotForwardedError]); + } + return; + } + FIRVerificationResultCallback callback = + ^(NSString *_Nullable verificationID, NSError *_Nullable error) { + if (completion) { + completion(verificationID, error); + } + }; + [self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber + retryOnInvalidAppCredential:YES + UIDelegate:UIDelegate + multiFactorSession:session + callback:callback]; + }]; +} + +/** @fn verifyClientAndSendVerificationCodeToPhoneNumber:retryOnInvalidAppCredential:callback: + @brief Starts the flow to verify the client via silent push notification. + @param retryOnInvalidAppCredential Whether of not the flow should be retried if an + FIRAuthErrorCodeInvalidAppCredential error is returned from the backend. + @param phoneNumber The phone number to be verified. + @param callback The callback to be invoked on the global work queue when the flow is + finished. + */ +- (void)verifyClientAndSendVerificationCodeToPhoneNumber:(NSString *)phoneNumber + retryOnInvalidAppCredential:(BOOL)retryOnInvalidAppCredential + UIDelegate:(nullable id)UIDelegate + callback:(FIRVerificationResultCallback)callback { + if (_auth.settings.isAppVerificationDisabledForTesting) { + FIRSendVerificationCodeRequest *request = + [[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber + appCredential:nil + reCAPTCHAToken:nil + requestConfiguration:_auth.requestConfiguration]; + [FIRAuthBackend sendVerificationCode:request + callback:^(FIRSendVerificationCodeResponse *_Nullable response, + NSError *_Nullable error) { + callback(response.verificationID, error); + }]; + return; + } + [self + verifyClientWithUIDelegate:UIDelegate + completion:^(FIRAuthAppCredential *_Nullable appCredential, + NSString *_Nullable reCAPTCHAToken, NSError *_Nullable error) { + if (error) { + callback(nil, error); + return; + } + FIRSendVerificationCodeRequest *_Nullable request; + if (appCredential) { + request = [[FIRSendVerificationCodeRequest alloc] + initWithPhoneNumber:phoneNumber + appCredential:appCredential + reCAPTCHAToken:nil + requestConfiguration:self->_auth.requestConfiguration]; + } else if (reCAPTCHAToken) { + request = [[FIRSendVerificationCodeRequest alloc] + initWithPhoneNumber:phoneNumber + appCredential:nil + reCAPTCHAToken:reCAPTCHAToken + requestConfiguration:self->_auth.requestConfiguration]; + } + if (request) { + [FIRAuthBackend + sendVerificationCode:request + callback:^( + FIRSendVerificationCodeResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (error.code == + FIRAuthErrorCodeInvalidAppCredential) { + if (retryOnInvalidAppCredential) { + [self->_auth + .appCredentialManager clearCredential]; + [self + verifyClientAndSendVerificationCodeToPhoneNumber: + phoneNumber + retryOnInvalidAppCredential: + NO + UIDelegate: + UIDelegate + callback: + callback]; + return; + } + callback( + nil, + [FIRAuthErrorUtils + unexpectedResponseWithDeserializedResponse: + nil + underlyingError: + error]); + return; + } + callback(nil, error); + return; + } + callback(response.verificationID, nil); + }]; + } + }]; +} + +- (void)verifyClientAndSendVerificationCodeToPhoneNumber:(NSString *)phoneNumber + retryOnInvalidAppCredential:(BOOL)retryOnInvalidAppCredential + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + callback:(FIRVerificationResultCallback)callback { + if (_auth.settings.isAppVerificationDisabledForTesting) { + FIRSendVerificationCodeRequest *request = + [[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber + appCredential:nil + reCAPTCHAToken:nil + requestConfiguration:_auth.requestConfiguration]; + [FIRAuthBackend sendVerificationCode:request + callback:^(FIRSendVerificationCodeResponse *_Nullable response, + NSError *_Nullable error) { + callback(response.verificationID, error); + }]; + return; + } + + [self + verifyClientWithUIDelegate:UIDelegate + completion:^(FIRAuthAppCredential *_Nullable appCredential, + NSString *_Nullable reCAPTCHAToken, NSError *_Nullable error) { + if (error) { + if (callback) { + callback(nil, error); + } + return; + } + + NSString *IDToken = session.IDToken; + FIRAuthProtoStartMFAPhoneRequestInfo *startMFARequestInfo = + [[FIRAuthProtoStartMFAPhoneRequestInfo alloc] + initWithPhoneNumber:phoneNumber + appCredential:appCredential + reCAPTCHAToken:reCAPTCHAToken]; + if (session.IDToken) { + FIRStartMFAEnrollmentRequest *request = + [[FIRStartMFAEnrollmentRequest alloc] + initWithIDToken:IDToken + enrollmentInfo:startMFARequestInfo + requestConfiguration:self->_auth.requestConfiguration]; + [FIRAuthBackend + startMultiFactorEnrollment:request + callback:^(FIRStartMFAEnrollmentResponse + *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (error.code == + FIRAuthErrorCodeInvalidAppCredential) { + if (retryOnInvalidAppCredential) { + [self->_auth.appCredentialManager + clearCredential]; + [self + verifyClientAndSendVerificationCodeToPhoneNumber: + phoneNumber + retryOnInvalidAppCredential: + NO + UIDelegate: + UIDelegate + multiFactorSession: + session + callback: + callback]; + return; + } + if (callback) { + callback( + nil, + [FIRAuthErrorUtils + unexpectedResponseWithDeserializedResponse: + nil + underlyingError: + error]); + } + return; + } else { + if (callback) { + callback(nil, error); + } + } + } else { + if (callback) { + callback( + response.enrollmentResponse.sessionInfo, + nil); + } + } + }]; + } else { + FIRStartMFASignInRequest *request = [[FIRStartMFASignInRequest alloc] + initWithMFAPendingCredential:session.MFAPendingCredential + MFAEnrollmentID:session.multiFactorInfo.UID + signInInfo:startMFARequestInfo + requestConfiguration:self->_auth.requestConfiguration]; + [FIRAuthBackend + startMultiFactorSignIn:request + callback:^( + FIRStartMFASignInResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (error.code == + FIRAuthErrorCodeInvalidAppCredential) { + if (retryOnInvalidAppCredential) { + [self->_auth + .appCredentialManager clearCredential]; + [self + verifyClientAndSendVerificationCodeToPhoneNumber: + phoneNumber + retryOnInvalidAppCredential: + NO + UIDelegate: + UIDelegate + multiFactorSession: + session + callback: + callback]; + return; + } + if (callback) { + callback( + nil, + [FIRAuthErrorUtils + unexpectedResponseWithDeserializedResponse: + nil + underlyingError: + error]); + } + return; + } else { + if (callback) { + callback(nil, error); + } + } + } else { + if (callback) { + callback(response.responseInfo.sessionInfo, nil); + } + } + }]; + } + }]; +} + +/** @fn verifyClientWithCompletion:completion: + @brief Continues the flow to verify the client via silent push notification. + @param completion The callback to be invoked when the client verification flow is finished. + */ +- (void)verifyClientWithUIDelegate:(nullable id)UIDelegate + completion:(FIRVerifyClientCallback)completion { + if (_auth.appCredentialManager.credential) { + completion(_auth.appCredentialManager.credential, nil, nil); + return; + } + [_auth.tokenManager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, + NSError *_Nullable error) { + if (!token) { + [self reCAPTCHAFlowWithUIDelegate:UIDelegate completion:completion]; + return; + } + FIRVerifyClientRequest *request = + [[FIRVerifyClientRequest alloc] initWithAppToken:token.string + isSandbox:token.type == FIRAuthAPNSTokenTypeSandbox + requestConfiguration:self->_auth.requestConfiguration]; + [FIRAuthBackend + verifyClient:request + callback:^(FIRVerifyClientResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey]; + BOOL isInvalidAppCredential = + error.code == FIRAuthErrorCodeInternalError && + underlyingError.code == FIRAuthErrorCodeInvalidAppCredential; + if (error.code != FIRAuthErrorCodeMissingAppToken && !isInvalidAppCredential) { + completion(nil, nil, error); + return; + } else { + [self reCAPTCHAFlowWithUIDelegate:UIDelegate completion:completion]; + return; + } + } + NSTimeInterval timeout = [response.suggestedTimeOutDate timeIntervalSinceNow]; + [self->_auth.appCredentialManager + didStartVerificationWithReceipt:response.receipt + timeout:timeout + callback:^(FIRAuthAppCredential *credential) { + if (!credential.secret) { + FIRLogWarning(kFIRLoggerAuth, @"I-AUT000014", + @"Failed to receive remote notification " + @"to verify app identity within " + @"%.0f second(s)", + timeout); + } + completion(credential, nil, nil); + }]; + }]; + }]; +} + +- (void)reCAPTCHAFlowWithUIDelegate:(nullable id)UIDelegate + completion:(FIRVerifyClientCallback)completion { + NSString *eventID = [FIRAuthWebUtils randomStringWithLength:10]; + [self + reCAPTCHAURLWithEventID:eventID + completion:^(NSURL *_Nullable reCAPTCHAURL, NSError *_Nullable error) { + if (error) { + completion(nil, nil, error); + return; + } + FIRAuthURLCallbackMatcher callbackMatcher = + ^BOOL(NSURL *_Nullable callbackURL) { + return [FIRAuthWebUtils isExpectedCallbackURL:callbackURL + eventID:eventID + authType:kAuthTypeVerifyApp + callbackScheme:self->_callbackScheme]; + }; + [self->_auth.authURLPresenter + presentURL:reCAPTCHAURL + UIDelegate:UIDelegate + callbackMatcher:callbackMatcher + completion:^(NSURL *_Nullable callbackURL, NSError *_Nullable error) { + if (error) { + completion(nil, nil, error); + return; + } + NSError *reCAPTCHAError; + NSString *reCAPTCHAToken = + [self reCAPTCHATokenForURL:callbackURL error:&reCAPTCHAError]; + if (!reCAPTCHAToken) { + completion(nil, nil, reCAPTCHAError); + return; + } else { + completion(nil, reCAPTCHAToken, nil); + return; + } + }]; + }]; +} + +/** @fn reCAPTCHAURLWithEventID:completion: + @brief Constructs a URL used for opening a reCAPTCHA app verification flow using a given event + ID. + @param eventID The event ID used for this purpose. + @param completion The callback invoked after the URL has been constructed or an error + has been encountered. + */ +- (void)reCAPTCHAURLWithEventID:(NSString *)eventID completion:(FIRReCAPTCHAURLCallBack)completion { + [FIRAuthWebUtils + fetchAuthDomainWithRequestConfiguration:_auth.requestConfiguration + completion:^(NSString *_Nullable authDomain, + NSError *_Nullable error) { + if (error) { + if (completion) { + completion(nil, error); + return; + } + } + NSString *bundleID = [NSBundle mainBundle].bundleIdentifier; + NSString *clientID = self->_auth.app.options.clientID; + NSString *apiKey = self->_auth.requestConfiguration.APIKey; + NSMutableArray *queryItems = [@[ + [NSURLQueryItem queryItemWithName:@"apiKey" value:apiKey], + [NSURLQueryItem queryItemWithName:@"authType" + value:kAuthTypeVerifyApp], + [NSURLQueryItem queryItemWithName:@"ibi" + value:bundleID ?: @""], + [NSURLQueryItem queryItemWithName:@"clientId" + value:clientID], + [NSURLQueryItem + queryItemWithName:@"v" + value:[FIRAuthBackend authUserAgent]], + [NSURLQueryItem queryItemWithName:@"eventId" value:eventID] + ] mutableCopy]; + + if (self->_auth.requestConfiguration.languageCode) { + [queryItems + addObject:[NSURLQueryItem + queryItemWithName:@"hl" + value:self->_auth + .requestConfiguration + .languageCode]]; + } + NSURLComponents *components = [[NSURLComponents alloc] + initWithString: + [NSString stringWithFormat:kReCAPTCHAURLStringFormat, + authDomain]]; + [components setQueryItems:queryItems]; + if (completion) { + completion([components URL], nil); + } + }]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h new file mode 100644 index 00000000..ad25dc6b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRTwitterAuthCredential + @brief Internal implementation of FIRAuthCredential for Twitter credentials. + */ +@interface FIRTwitterAuthCredential : FIRAuthCredential + +/** @property token + @brief The Twitter OAuth token. + */ +@property(nonatomic, readonly) NSString *token; + +/** @property secret + @brief The Twitter OAuth secret. + */ +@property(nonatomic, readonly) NSString *secret; + +/** @fn initWithToken:secret: + @brief Designated initializer. + @param token The Twitter OAuth token. + @param secret The Twitter OAuth secret. + */ +- (nullable instancetype)initWithToken:(NSString *)token + secret:(NSString *)secret NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.m new file mode 100644 index 00000000..8b83420b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h" + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRTwitterAuthCredential () + +- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE; + +@end + +@implementation FIRTwitterAuthCredential + +- (nullable instancetype)initWithProvider:(NSString *)provider { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"Please call the designated initializer."]; + return nil; +} + +- (nullable instancetype)initWithToken:(NSString *)token secret:(NSString *)secret { + self = [super initWithProvider:FIRTwitterAuthProviderID]; + if (self) { + _token = [token copy]; + _secret = [secret copy]; + } + return self; +} + +- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request { + request.providerAccessToken = _token; + request.providerOAuthTokenSecret = _secret; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *token = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"token"]; + NSString *secret = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"secret"]; + self = [self initWithToken:token secret:secret]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.token forKey:@"token"]; + [aCoder encodeObject:self.secret forKey:@"secret"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthProvider.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthProvider.m new file mode 100644 index 00000000..121fae4b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthProvider.m @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +// FIRTwitterAuthProviderID is defined in FIRAuthProvider.m. + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRTwitterAuthProvider + +- (instancetype)init { + [FIRAuthExceptionUtils + raiseMethodNotImplementedExceptionWithReason:@"This class is not meant to be initialized."]; + return nil; +} + ++ (FIRAuthCredential *)credentialWithToken:(NSString *)token secret:(NSString *)secret { + return [[FIRTwitterAuthCredential alloc] initWithToken:token secret:secret]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h new file mode 100644 index 00000000..34b38925 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h @@ -0,0 +1,125 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRStartMFAEnrollmentResponseCallback + @brief The type of block used to return the result of a call to the startMFAEnroll endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. +*/ +typedef void (^FIRStartMFAEnrollmentResponseCallback)( + FIRStartMFAEnrollmentResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRFinalizeMFAEnrollmentResponseCallback + @brief The type of block used to return the result of a call to the finalizeMFAEnroll endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. +*/ +typedef void (^FIRFinalizeMFAEnrollmentResponseCallback)( + FIRFinalizeMFAEnrollmentResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRStartMFASignInResponseCallback + @brief The type of block used to return the result of a call to the startMFASignIn endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. +*/ +typedef void (^FIRStartMFASignInResponseCallback)(FIRStartMFASignInResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRFinalizeMFASignInResponseCallback + @brief The type of block used to return the result of a call to the finalizeMFASignIn endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. +*/ +typedef void (^FIRFinalizeMFASignInResponseCallback)( + FIRFinalizeMFASignInResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRWithdrawMFAResponseCallback + @brief The type of block used to return the result of a call to the MFAUnenroll endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. +*/ +typedef void (^FIRWithdrawMFAResponseCallback)(FIRWithdrawMFAResponse *_Nullable response, + NSError *_Nullable error); + +@interface FIRAuthBackend (MultiFactor) + +/** @fn startMultiFactorEnrollment:callback: + @brief Calls the startMFAEnrollment endpoint. + @param request The request parameters. + @param callback The callback. +*/ ++ (void)startMultiFactorEnrollment:(FIRStartMFAEnrollmentRequest *)request + callback:(FIRStartMFAEnrollmentResponseCallback)callback; + +/** @fn finalizeMultiFactorEnrollment:callback: + @brief Calls the finalizeMultiFactorEnrollment endpoint. + @param request The request parameters. + @param callback The callback. +*/ ++ (void)finalizeMultiFactorEnrollment:(FIRFinalizeMFAEnrollmentRequest *)request + callback:(FIRFinalizeMFAEnrollmentResponseCallback)callback; + +/** @fn startMultiFactorSignIn:callback: + @brief Calls the startMultiFactorSignIn endpoint. + @param request The request parameters. + @param callback The callback. +*/ ++ (void)startMultiFactorSignIn:(FIRStartMFASignInRequest *)request + callback:(FIRStartMFASignInResponseCallback)callback; + +/** @fn finalizeMultiFactorSignIn:callback: + @brief Calls the finalizeMultiFactorSignIn endpoint. + @param request The request parameters. + @param callback The callback. +*/ ++ (void)finalizeMultiFactorSignIn:(FIRFinalizeMFASignInRequest *)request + callback:(FIRFinalizeMFASignInResponseCallback)callback; + +/** @fn withdrawMultiFactor:callback: + @brief Calls the withdrawMultiFactor endpoint. + @param request The request parameters. + @param callback The callback. +*/ ++ (void)withdrawMultiFactor:(FIRWithdrawMFARequest *)request + callback:(FIRWithdrawMFAResponseCallback)callback; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.m new file mode 100644 index 00000000..147fc7be --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.m @@ -0,0 +1,96 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h" + +@implementation FIRAuthBackend (MultiFactor) + ++ (void)startMultiFactorEnrollment:(FIRStartMFAEnrollmentRequest *)request + callback:(FIRStartMFAEnrollmentResponseCallback)callback { + FIRStartMFAEnrollmentResponse *response = [[FIRStartMFAEnrollmentResponse alloc] init]; + [[self implementation] postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + ++ (void)finalizeMultiFactorEnrollment:(FIRFinalizeMFAEnrollmentRequest *)request + callback:(FIRFinalizeMFAEnrollmentResponseCallback)callback { + FIRFinalizeMFAEnrollmentResponse *response = [[FIRFinalizeMFAEnrollmentResponse alloc] init]; + [[self implementation] postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + ++ (void)startMultiFactorSignIn:(FIRStartMFASignInRequest *)request + callback:(FIRStartMFASignInResponseCallback)callback { + FIRStartMFASignInResponse *response = [[FIRStartMFASignInResponse alloc] init]; + [[self implementation] postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + ++ (void)finalizeMultiFactorSignIn:(FIRFinalizeMFASignInRequest *)request + callback:(FIRFinalizeMFASignInResponseCallback)callback { + FIRFinalizeMFASignInResponse *response = [[FIRFinalizeMFASignInResponse alloc] init]; + [[self implementation] postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + ++ (void)withdrawMultiFactor:(FIRWithdrawMFARequest *)request + callback:(FIRWithdrawMFAResponseCallback)callback { + FIRWithdrawMFAResponse *response = [[FIRWithdrawMFAResponse alloc] init]; + [[self implementation] postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +@end + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.h new file mode 100644 index 00000000..d3e9bca4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.h @@ -0,0 +1,620 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +@class FIRAuthRequestConfiguration; +@class FIRCreateAuthURIRequest; +@class FIRCreateAuthURIResponse; +@class FIRDeleteAccountRequest; +@class FIRDeleteAccountResponse; +@class FIREmailLinkSignInRequest; +@class FIREmailLinkSignInResponse; +@class FIRGetAccountInfoRequest; +@class FIRGetAccountInfoResponse; +@class FIRGetProjectConfigRequest; +@class FIRGetProjectConfigResponse; +@class FIRGetOOBConfirmationCodeRequest; +@class FIRGetOOBConfirmationCodeResponse; +@class FIRResetPasswordRequest; +@class FIRResetPasswordResponse; +@class FIRSecureTokenRequest; +@class FIRSecureTokenResponse; +@class FIRSetAccountInfoRequest; +@class FIRSetAccountInfoResponse; +@class FIRVerifyAssertionRequest; +@class FIRVerifyAssertionResponse; +@class FIRVerifyClientRequest; +@class FIRVerifyClientResponse; +@class FIRVerifyCustomTokenRequest; +@class FIRVerifyCustomTokenResponse; +@class FIRVerifyPasswordRequest; +@class FIRVerifyPasswordResponse; +@class FIRVerifyPhoneNumberRequest; +@class FIRVerifyPhoneNumberResponse; +@class FIRSendVerificationCodeRequest; +@class FIRSendVerificationCodeResponse; +@class FIRSignInWithGameCenterRequest; +@class FIRSignInWithGameCenterResponse; +@class FIRSignUpNewUserRequest; +@class FIRSignUpNewUserResponse; + +@protocol FIRAuthBackendImplementation; +@protocol FIRAuthBackendRPCIssuer; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthBackendRPCIssuerCompletionHandler + @brief The type of block used to return the result of a call to an endpoint. + @param data The HTTP response body. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRAuthBackendRPCIssuerCompletionHandler)(NSData *_Nullable data, + NSError *_Nullable error); + +/** @typedef FIRCreateAuthURIResponseCallback + @brief The type of block used to return the result of a call to the createAuthURI + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRCreateAuthURIResponseCallback)(FIRCreateAuthURIResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRGetAccountInfoResponseCallback + @brief The type of block used to return the result of a call to the getAccountInfo + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRGetAccountInfoResponseCallback)(FIRGetAccountInfoResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRGetProjectConfigResponseCallback + @brief The type of block used to return the result of a call to the getProjectInfo + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRGetProjectConfigResponseCallback)(FIRGetProjectConfigResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRSetAccountInfoResponseCallback + @brief The type of block used to return the result of a call to the setAccountInfo + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRSetAccountInfoResponseCallback)(FIRSetAccountInfoResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRSecureTokenResponseCallback + @brief The type of block used to return the result of a call to the token endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRSecureTokenResponseCallback)(FIRSecureTokenResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRVerifyAssertionResponseCallback + @brief The type of block used to return the result of a call to the verifyAssertion + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRVerifyAssertionResponseCallback)(FIRVerifyAssertionResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRVerifyPasswordResponseCallback + @brief The type of block used to return the result of a call to the verifyPassword + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRVerifyPasswordResponseCallback)(FIRVerifyPasswordResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIREmailLinkSigninResponseCallback + @brief The type of block used to return the result of a call to the emailLinkSignin + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIREmailLinkSigninResponseCallback)(FIREmailLinkSignInResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRVerifyCustomTokenResponseCallback + @brief The type of block used to return the result of a call to the verifyCustomToken + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRVerifyCustomTokenResponseCallback)( + FIRVerifyCustomTokenResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRDeleteCallBack + @brief The type of block called when a request delete account has finished. + @param error The error which occurred, or nil if the request was successful. + */ +typedef void (^FIRDeleteCallBack)(NSError *_Nullable error); + +/** @typedef FIRGetOOBConfirmationCodeResponseCallback + @brief The type of block used to return the result of a call to the getOOBConfirmationCode + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRGetOOBConfirmationCodeResponseCallback)( + FIRGetOOBConfirmationCodeResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRSignupNewUserCallback + @brief The type of block used to return the result of a call to the signupNewUser endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRSignupNewUserCallback)(FIRSignUpNewUserResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRResetPasswordCallback + @brief The type of block used to return the result of a call to the resetPassword endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRResetPasswordCallback)(FIRResetPasswordResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRSendVerificationCodeResponseCallback + @brief The type of block used to return the result of a call to the sendVerificationCode + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRSendVerificationCodeResponseCallback)( + FIRSendVerificationCodeResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRVerifyPhoneNumberResponseCallback + @brief The type of block used to return the result of a call to the verifyPhoneNumber endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRVerifyPhoneNumberResponseCallback)( + FIRVerifyPhoneNumberResponse *_Nullable response, NSError *_Nullable error); + +/** @typedef FIRVerifyClientResponseCallback + @brief The type of block used to return the result of a call to the verifyClient endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRVerifyClientResponseCallback)(FIRVerifyClientResponse *_Nullable response, + NSError *_Nullable error); + +/** @typedef FIRSignInWithGameCenterResponseCallback + @brief The type of block used to return the result of a call to the SignInWithGameCenter + endpoint. + @param response The received response, if any. + @param error The error which occurred, if any. + @remarks One of response or error will be non-nil. + */ +typedef void (^FIRSignInWithGameCenterResponseCallback)( + FIRSignInWithGameCenterResponse *_Nullable response, NSError *_Nullable error); + +/** @class FIRAuthBackend + @brief Simple static class with methods representing the backend RPCs. + @remarks All callback blocks passed as method parameters are invoked asynchronously on the + global work queue in the future. See + https://github.com/firebase/firebase-ios-sdk/tree/master/FirebaseAuth/Docs/threading.md + */ +@interface FIRAuthBackend : NSObject + +/** @fn authUserAgent + @brief Retrieves the Firebase Auth user agent. + @return The Firebase Auth user agent. + */ ++ (NSString *)authUserAgent; + ++ (id)implementation; + +/** @fn setBackendImplementation: + @brief Changes the default backend implementation to something else. + @param backendImplementation The backend implementation to use. + @remarks This is not, generally, safe to call in a scenario where other backend requests may + be occuring. This is specifically to help mock the backend for testing purposes. + */ ++ (void)setBackendImplementation:(id)backendImplementation; + +/** @fn setDefaultBackendImplementationWithRPCIssuer: + @brief Uses the default backend implementation, but with a custom RPC issuer. + @param RPCIssuer The RPC issuer to use. If @c nil, will use the default implementation. + @remarks This is not, generally, safe to call in a scenario where other backend requests may + be occuring. This is specifically to help test the backend interfaces (requests, responses, + and shared FIRAuthBackend logic.) + */ ++ (void)setDefaultBackendImplementationWithRPCIssuer: + (nullable id)RPCIssuer; + +/** @fn createAuthURI:callback: + @brief Calls the createAuthURI endpoint, which is responsible for creating the URI used by the + IdP to authenticate the user. + @param request The request parameters. + @param callback The callback. + */ ++ (void)createAuthURI:(FIRCreateAuthURIRequest *)request + callback:(FIRCreateAuthURIResponseCallback)callback; + +/** @fn getAccountInfo:callback: + @brief Calls the getAccountInfo endpoint, which returns account info for a given account. + @param request The request parameters. + @param callback The callback. + */ ++ (void)getAccountInfo:(FIRGetAccountInfoRequest *)request + callback:(FIRGetAccountInfoResponseCallback)callback; + +/** @fn getProjectConfig:callback: + @brief Calls the getProjectConfig endpoint, which returns configuration information for a given + project. + @param request An object wrapping the backend get request. + @param callback The callback. + */ ++ (void)getProjectConfig:(FIRGetProjectConfigRequest *)request + callback:(FIRGetProjectConfigResponseCallback)callback; + +/** @fn setAccountInfo:callback: + @brief Calls the setAccountInfo endpoint, which is responsible for setting account info for a + user, for example, to sign up a new user with email and password. + @param request The request parameters. + @param callback The callback. + */ ++ (void)setAccountInfo:(FIRSetAccountInfoRequest *)request + callback:(FIRSetAccountInfoResponseCallback)callback; + +/** @fn verifyAssertion:callback: + @brief Calls the verifyAssertion endpoint, which is responsible for authenticating a + user who has IDP-related credentials (an ID Token, an Access Token, etc.) + @param request The request parameters. + @param callback The callback. + */ ++ (void)verifyAssertion:(FIRVerifyAssertionRequest *)request + callback:(FIRVerifyAssertionResponseCallback)callback; + +/** @fn verifyCustomToken:callback: + @brief Calls the verifyCustomToken endpoint, which is responsible for authenticating a + user who has BYOAuth credentials (a self-signed token using their BYOAuth private key.) + @param request The request parameters. + @param callback The callback. + */ ++ (void)verifyCustomToken:(FIRVerifyCustomTokenRequest *)request + callback:(FIRVerifyCustomTokenResponseCallback)callback; + +/** @fn verifyPassword:callback: + @brief Calls the verifyPassword endpoint, which is responsible for authenticating a + user who has email and password credentials. + @param request The request parameters. + @param callback The callback. + */ ++ (void)verifyPassword:(FIRVerifyPasswordRequest *)request + callback:(FIRVerifyPasswordResponseCallback)callback; + +/** @fn emailLinkSignin:callback: + @brief Calls the emailLinkSignin endpoint, which is responsible for authenticating a + user through passwordless sign-in. + @param request The request parameters. + @param callback The callback. + */ ++ (void)emailLinkSignin:(FIREmailLinkSignInRequest *)request + callback:(FIREmailLinkSigninResponseCallback)callback; + +/** @fn secureToken:callback: + @brief Calls the token endpoint, which is responsible for performing STS token exchanges and + token refreshes. + @param request The request parameters. + @param callback The callback. + */ ++ (void)secureToken:(FIRSecureTokenRequest *)request + callback:(FIRSecureTokenResponseCallback)callback; + +/** @fn getOOBConfirmationCode:callback: + @brief Calls the getOOBConfirmationCode endpoint, which is responsible for sending email change + request emails, and password reset emails. + @param request The request parameters. + @param callback The callback. + */ ++ (void)getOOBConfirmationCode:(FIRGetOOBConfirmationCodeRequest *)request + callback:(FIRGetOOBConfirmationCodeResponseCallback)callback; + +/** @fn signUpNewUser: + @brief Calls the signUpNewUser endpoint, which is responsible anonymously signing up a user + or signing in a user anonymously. + @param request The request parameters. + @param callback The callback. + */ ++ (void)signUpNewUser:(FIRSignUpNewUserRequest *)request + callback:(FIRSignupNewUserCallback)callback; + +/** @fn resetPassword:callback + @brief Calls the resetPassword endpoint, which is responsible for resetting a user's password + given an OOB code and new password. + @param request The request parameters. + @param callback The callback. + */ ++ (void)resetPassword:(FIRResetPasswordRequest *)request + callback:(FIRResetPasswordCallback)callback; + +/** @fn deleteAccount: + @brief Calls the DeleteAccount endpoint, which is responsible for deleting a user. + @param request The request parameters. + @param callback The callback. + */ ++ (void)deleteAccount:(FIRDeleteAccountRequest *)request callback:(FIRDeleteCallBack)callback; + +/** @fn SignInWithGameCenter:callback: + @brief Calls the SignInWithGameCenter endpoint, which is responsible for authenticating a user + who has Game Center credentials. + @param request The request parameters. + @param callback The callback. + */ ++ (void)signInWithGameCenter:(FIRSignInWithGameCenterRequest *)request + callback:(FIRSignInWithGameCenterResponseCallback)callback; + +#if TARGET_OS_IOS +/** @fn sendVerificationCode:callback: + @brief Calls the sendVerificationCode endpoint, which is responsible for sending the + verification code to a phone number specified in the request parameters. + @param request The request parameters. + @param callback The callback. + */ ++ (void)sendVerificationCode:(FIRSendVerificationCodeRequest *)request + callback:(FIRSendVerificationCodeResponseCallback)callback; + +/** @fn verifyPhoneNumber:callback: + @brief Calls the verifyPhoneNumber endpoint, which is responsible for sending the verification + code to a phone number specified in the request parameters. + @param request The request parameters. + @param callback The callback. + */ ++ (void)verifyPhoneNumber:(FIRVerifyPhoneNumberRequest *)request + callback:(FIRVerifyPhoneNumberResponseCallback)callback; + +/** @fn verifyClient:callback: + @brief Calls the verifyClient endpoint, which is responsible for sending the silent push + notification used for app validation to the device provided in the request parameters. + @param request The request parameters. + @param callback The callback. + */ ++ (void)verifyClient:(FIRVerifyClientRequest *)request + callback:(FIRVerifyClientResponseCallback)callback; +#endif + +@end + +/** @protocol FIRAuthBackendRPCIssuer + @brief Used to make FIRAuthBackend + */ +@protocol FIRAuthBackendRPCIssuer + +/** @fn asyncPostToURLWithRequestConfiguration:URL:body:contentType:completionHandler: + @brief Asynchronously seXnds a POST request. + @param requestConfiguration The request to be made. + @param URL The request URL. + @param body Request body. + @param contentType Content type of the body. + @param handler provided that handles POST response. Invoked asynchronously on the auth global + work queue in the future. + */ +- (void)asyncPostToURLWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + URL:(NSURL *)URL + body:(nullable NSData *)body + contentType:(NSString *)contentType + completionHandler:(FIRAuthBackendRPCIssuerCompletionHandler)handler; + +@end + +/** @protocol FIRAuthBackendImplementation + @brief Used to make FIRAuthBackend provide a layer of indirection to an actual RPC-based backend + or a mock backend. + */ +@protocol FIRAuthBackendImplementation + +/** @fn createAuthURI:callback: + @brief Calls the createAuthURI endpoint, which is responsible for creating the URI used by the + IdP to authenticate the user. + @param request The request parameters. + @param callback The callback. + */ +- (void)createAuthURI:(FIRCreateAuthURIRequest *)request + callback:(FIRCreateAuthURIResponseCallback)callback; + +/** @fn getAccountInfo:callback: + @brief Calls the getAccountInfo endpoint, which returns account info for a given account. + @param request The request parameters. + @param callback The callback. + */ +- (void)getAccountInfo:(FIRGetAccountInfoRequest *)request + callback:(FIRGetAccountInfoResponseCallback)callback; + +/** @fn getProjectConfig:callback: + @brief Calls the getProjectInfo endpoint, which returns configuration information for a given + project. + @param request The request parameters. + @param callback The callback. + */ +- (void)getProjectConfig:(FIRGetProjectConfigRequest *)request + callback:(FIRGetProjectConfigResponseCallback)callback; + +/** @fn setAccountInfo:callback: + @brief Calls the setAccountInfo endpoint, which is responsible for setting account info for a + user, for example, to sign up a new user with email and password. + @param request The request parameters. + @param callback The callback. + */ +- (void)setAccountInfo:(FIRSetAccountInfoRequest *)request + callback:(FIRSetAccountInfoResponseCallback)callback; + +/** @fn verifyAssertion:callback: + @brief Calls the verifyAssertion endpoint, which is responsible for authenticating a + user who has IDP-related credentials (an ID Token, an Access Token, etc.) + @param request The request parameters. + @param callback The callback. + */ +- (void)verifyAssertion:(FIRVerifyAssertionRequest *)request + callback:(FIRVerifyAssertionResponseCallback)callback; + +/** @fn verifyCustomToken:callback: + @brief Calls the verifyCustomToken endpoint, which is responsible for authenticating a + user who has BYOAuth credentials (a self-signed token using their BYOAuth private key.) + @param request The request parameters. + @param callback The callback. + */ +- (void)verifyCustomToken:(FIRVerifyCustomTokenRequest *)request + callback:(FIRVerifyCustomTokenResponseCallback)callback; + +/** @fn verifyPassword:callback: + @brief Calls the verifyPassword endpoint, which is responsible for authenticating a + user who has email and password credentials. + @param request The request parameters. + @param callback The callback. + */ +- (void)verifyPassword:(FIRVerifyPasswordRequest *)request + callback:(FIRVerifyPasswordResponseCallback)callback; + +/** @fn emailLinkSignin:callback: + @brief Calls the emailLinkSignin endpoint, which is responsible for authenticating a + user through passwordless sign-in. + @param request The request parameters. + @param callback The callback. + */ +- (void)emailLinkSignin:(FIREmailLinkSignInRequest *)request + callback:(FIREmailLinkSigninResponseCallback)callback; + +/** @fn secureToken:callback: + @brief Calls the token endpoint, which is responsible for performing STS token exchanges and + token refreshes. + @param request The request parameters. + @param callback The callback. + */ +- (void)secureToken:(FIRSecureTokenRequest *)request + callback:(FIRSecureTokenResponseCallback)callback; + +/** @fn getOOBConfirmationCode:callback: + @brief Calls the getOOBConfirmationCode endpoint, which is responsible for sending email change + request emails, email sign-in link emails, and password reset emails. + @param request The request parameters. + @param callback The callback. + */ +- (void)getOOBConfirmationCode:(FIRGetOOBConfirmationCodeRequest *)request + callback:(FIRGetOOBConfirmationCodeResponseCallback)callback; + +/** @fn signUpNewUser: + @brief Calls the signUpNewUser endpoint, which is responsible anonymously signing up a user + or signing in a user anonymously. + @param request The request parameters. + @param callback The callback. + */ +- (void)signUpNewUser:(FIRSignUpNewUserRequest *)request + callback:(FIRSignupNewUserCallback)callback; + +/** @fn deleteAccount: + @brief Calls the DeleteAccount endpoint, which is responsible for deleting a user. + @param request The request parameters. + @param callback The callback. + */ +- (void)deleteAccount:(FIRDeleteAccountRequest *)request callback:(FIRDeleteCallBack)callback; + +#if TARGET_OS_IOS +/** @fn sendVerificationCode:callback: + @brief Calls the sendVerificationCode endpoint, which is responsible for sending the + verification code to a phone number specified in the request parameters. + @param request The request parameters. + @param callback The callback. + */ +- (void)sendVerificationCode:(FIRSendVerificationCodeRequest *)request + callback:(FIRSendVerificationCodeResponseCallback)callback; + +/** @fn verifyPhoneNumber:callback: + @brief Calls the verifyPhoneNumber endpoint, which is responsible for sending the verification + code to a phone number specified in the request parameters. + @param request The request parameters. + @param callback The callback. + */ +- (void)verifyPhoneNumber:(FIRVerifyPhoneNumberRequest *)request + callback:(FIRVerifyPhoneNumberResponseCallback)callback; + +/** @fn verifyClient:callback: + @brief Calls the verifyClient endpoint, which is responsible for sending the silent push + notification used for app validation to the device provided in the request parameters. + @param request The request parameters. + @param callback The callback. + */ +- (void)verifyClient:(FIRVerifyClientRequest *)request + callback:(FIRVerifyClientResponseCallback)callback; +#endif + +/** @fn SignInWithGameCenter:callback: + @brief Calls the SignInWithGameCenter endpoint, which is responsible for authenticating a user + who has Game Center credentials. + @param request The request parameters. + @param callback The callback. + */ +- (void)signInWithGameCenter:(FIRSignInWithGameCenterRequest *)request + callback:(FIRSignInWithGameCenterResponseCallback)callback; + +/** @fn resetPassword:callback + @brief Calls the resetPassword endpoint, which is responsible for resetting a user's password + given an OOB code and new password. + @param request The request parameters. + @param callback The callback. + */ +- (void)resetPassword:(FIRResetPasswordRequest *)request + callback:(FIRResetPasswordCallback)callback; + +/** @fn postWithRequest:response:callback: + @brief Calls the RPC using HTTP POST. + @remarks Possible error responses: + @see FIRAuthInternalErrorCodeRPCRequestEncodingError + @see FIRAuthInternalErrorCodeJSONSerializationError + @see FIRAuthInternalErrorCodeNetworkError + @see FIRAuthInternalErrorCodeUnexpectedErrorResponse + @see FIRAuthInternalErrorCodeUnexpectedResponse + @see FIRAuthInternalErrorCodeRPCResponseDecodingError + @param request The request. + @param response The empty response to be filled. + @param callback The callback for both success and failure. +*/ +- (void)postWithRequest:(id)request + response:(id)response + callback:(void (^)(NSError *_Nullable error))callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.m new file mode 100644 index 00000000..6b7c90b9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthBackend.m @@ -0,0 +1,1404 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" + +#import +#import +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +#if TARGET_OS_IOS +#import + +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** @var kClientVersionHeader + @brief HTTP header name for the client version. + */ +static NSString *const kClientVersionHeader = @"X-Client-Version"; + +/** @var kIosBundleIdentifierHeader + @brief HTTP header name for iOS bundle ID. + */ +static NSString *const kIosBundleIdentifierHeader = @"X-Ios-Bundle-Identifier"; + +/** @var kFirebaseLocalHeader + @brief HTTP header name for the firebase locale. + */ +static NSString *const kFirebaseLocalHeader = @"X-Firebase-Locale"; + +/** @var kFirebaseAuthCoreFrameworkMarker + @brief The marker in the HTTP header that indicates the request comes from Firebase Auth Core. + */ +static NSString *const kFirebaseAuthCoreFrameworkMarker = @"FirebaseCore-iOS"; + +/** @var kJSONContentType + @brief The value of the HTTP content-type header for JSON payloads. + */ +static NSString *const kJSONContentType = @"application/json"; + +/** @var kErrorDataKey + @brief Key for error data in NSError returned by @c GTMSessionFetcher. + */ +static NSString *const kErrorDataKey = @"data"; + +/** @var kErrorKey + @brief The key for the "error" value in JSON responses from the server. + */ +static NSString *const kErrorKey = @"error"; + +/** @var kErrorsKey + @brief The key for the "errors" value in JSON responses from the server. + */ +static NSString *const kErrorsKey = @"errors"; + +/** @var kReasonKey + @brief The key for the "reason" value in JSON responses from the server. + */ +static NSString *const kReasonKey = @"reason"; + +/** @var kInvalidKeyReasonValue + @brief The value for the "reason" key indicating an invalid API Key was received by the server. + */ +static NSString *const kInvalidKeyReasonValue = @"keyInvalid"; + +/** @var kAppNotAuthorizedReasonValue + @brief The value for the "reason" key indicating the App is not authorized to use Firebase + Authentication. + */ +static NSString *const kAppNotAuthorizedReasonValue = @"ipRefererBlocked"; + +/** @var kErrorMessageKey + @brief The key for an error's "message" value in JSON responses from the server. + */ +static NSString *const kErrorMessageKey = @"message"; + +/** @var kReturnIDPCredentialErrorMessageKey + @brief The key for "errorMessage" value in JSON responses from the server, In case + returnIDPCredential of a verifyAssertion request is set to @YES. + */ +static NSString *const kReturnIDPCredentialErrorMessageKey = @"errorMessage"; + +/** @var kUserNotFoundErrorMessage + @brief This is the error message returned when the user is not found, which means the user + account has been deleted given the token was once valid. + */ +static NSString *const kUserNotFoundErrorMessage = @"USER_NOT_FOUND"; + +/** @var kUserDeletedErrorMessage + @brief This is the error message the server will respond with if the user entered an invalid + email address. + */ +static NSString *const kUserDeletedErrorMessage = @"EMAIL_NOT_FOUND"; + +/** @var kInvalidLocalIDErrorMessage + @brief This is the error message the server responds with if the user local id in the id token + does not exit. + */ +static NSString *const kInvalidLocalIDErrorMessage = @"INVALID_LOCAL_ID"; + +/** @var kUserTokenExpiredErrorMessage + @brief The error returned by the server if the token issue time is older than the account's + valid_since time. + */ +static NSString *const kUserTokenExpiredErrorMessage = @"TOKEN_EXPIRED"; + +/** @var kTooManyRequestsErrorMessage + @brief This is the error message the server will respond with if too many requests were made to + a server method. + */ +static NSString *const kTooManyRequestsErrorMessage = @"TOO_MANY_ATTEMPTS_TRY_LATER"; + +/** @var kInvalidCustomTokenErrorMessage + @brief This is the error message the server will respond with if there is a validation error + with the custom token. + */ +static NSString *const kInvalidCustomTokenErrorMessage = @"INVALID_CUSTOM_TOKEN"; + +/** @var kCustomTokenMismatch + @brief This is the error message the server will respond with if the service account and API key + belong to different projects. + */ +static NSString *const kCustomTokenMismatch = @"CREDENTIAL_MISMATCH"; + +/** @var kInvalidCredentialErrorMessage + @brief This is the error message the server responds with if the IDP token or requestUri is + invalid. + */ +static NSString *const kInvalidCredentialErrorMessage = @"INVALID_IDP_RESPONSE"; + +/** @var kUserDisabledErrorMessage + @brief The error returned by the server if the user account is diabled. + */ +static NSString *const kUserDisabledErrorMessage = @"USER_DISABLED"; + +/** @var kOperationNotAllowedErrorMessage + @brief This is the error message the server will respond with if Admin disables IDP specified by + provider. + */ +static NSString *const kOperationNotAllowedErrorMessage = @"OPERATION_NOT_ALLOWED"; + +/** @var kPasswordLoginDisabledErrorMessage + @brief This is the error message the server responds with if password login is disabled. + */ +static NSString *const kPasswordLoginDisabledErrorMessage = @"PASSWORD_LOGIN_DISABLED"; + +/** @var kEmailAlreadyInUseErrorMessage + @brief This is the error message the server responds with if the email address already exists. + */ +static NSString *const kEmailAlreadyInUseErrorMessage = @"EMAIL_EXISTS"; + +/** @var kInvalidEmailErrorMessage + @brief The error returned by the server if the email is invalid. + */ +static NSString *const kInvalidEmailErrorMessage = @"INVALID_EMAIL"; + +/** @var kInvalidIdentifierErrorMessage + @brief The error returned by the server if the identifier is invalid. + */ +static NSString *const kInvalidIdentifierErrorMessage = @"INVALID_IDENTIFIER"; + +/** @var kWrongPasswordErrorMessage + @brief This is the error message the server will respond with if the user entered a wrong + password. + */ +static NSString *const kWrongPasswordErrorMessage = @"INVALID_PASSWORD"; + +/** @var kCredentialTooOldErrorMessage + @brief This is the error message the server responds with if account change is attempted 5 + minutes after signing in. + */ +static NSString *const kCredentialTooOldErrorMessage = @"CREDENTIAL_TOO_OLD_LOGIN_AGAIN"; + +/** @var kFederatedUserIDAlreadyLinkedMessage + @brief This is the error message the server will respond with if the federated user ID has been + already linked with another account. + */ +static NSString *const kFederatedUserIDAlreadyLinkedMessage = @"FEDERATED_USER_ID_ALREADY_LINKED"; + +/** @var kInvalidUserTokenErrorMessage + @brief This is the error message the server responds with if user's saved auth credential is + invalid, and the user needs to sign in again. + */ +static NSString *const kInvalidUserTokenErrorMessage = @"INVALID_ID_TOKEN"; + +/** @var kWeakPasswordErrorMessagePrefix + @brief This is the prefix for the error message the server responds with if user's new password + to be set is too weak. + */ +static NSString *const kWeakPasswordErrorMessagePrefix = @"WEAK_PASSWORD"; + +/** @var kExpiredActionCodeErrorMessage + @brief This is the error message the server will respond with if the action code is expired. + */ +static NSString *const kExpiredActionCodeErrorMessage = @"EXPIRED_OOB_CODE"; + +/** @var kInvalidActionCodeErrorMessage + @brief This is the error message the server will respond with if the action code is invalid. + */ +static NSString *const kInvalidActionCodeErrorMessage = @"INVALID_OOB_CODE"; + +/** @var kMissingEmailErrorMessage + @brief This is the error message the server will respond with if the email address is missing + during a "send password reset email" attempt. + */ +static NSString *const kMissingEmailErrorMessage = @"MISSING_EMAIL"; + +/** @var kInvalidSenderEmailErrorMessage + @brief This is the error message the server will respond with if the sender email is invalid + during a "send password reset email" attempt. + */ +static NSString *const kInvalidSenderEmailErrorMessage = @"INVALID_SENDER"; + +/** @var kInvalidMessagePayloadErrorMessage + @brief This is the error message the server will respond with if there are invalid parameters in + the payload during a "send password reset email" attempt. + */ +static NSString *const kInvalidMessagePayloadErrorMessage = @"INVALID_MESSAGE_PAYLOAD"; + +/** @var kInvalidRecipientEmailErrorMessage + @brief This is the error message the server will respond with if the recipient email is invalid. + */ +static NSString *const kInvalidRecipientEmailErrorMessage = @"INVALID_RECIPIENT_EMAIL"; + +/** @var kMissingIosBundleIDErrorMessage + @brief This is the error message the server will respond with if iOS bundle ID is missing but + the iOS App store ID is provided. + */ +static NSString *const kMissingIosBundleIDErrorMessage = @"MISSING_IOS_BUNDLE_ID"; + +/** @var kMissingAndroidPackageNameErrorMessage + @brief This is the error message the server will respond with if Android Package Name is missing + but the flag indicating the app should be installed is set to true. + */ +static NSString *const kMissingAndroidPackageNameErrorMessage = @"MISSING_ANDROID_PACKAGE_NAME"; + +/** @var kUnauthorizedDomainErrorMessage + @brief This is the error message the server will respond with if the domain of the continue URL + specified is not whitelisted in the firebase console. + */ +static NSString *const kUnauthorizedDomainErrorMessage = @"UNAUTHORIZED_DOMAIN"; + +/** @var kInvalidProviderIDErrorMessage + @brief This is the error message the server will respond with if the provider id given for the + web operation is invalid. + */ +static NSString *const kInvalidProviderIDErrorMessage = @"INVALID_PROVIDER_ID"; + +/** @var kInvalidDynamicLinkDomainErrorMessage + @brief This is the error message the server will respond with if the dynamic link domain + provided in the request is invalid. + */ +static NSString *const kInvalidDynamicLinkDomainErrorMessage = @"INVALID_DYNAMIC_LINK_DOMAIN"; + +/** @var kInvalidContinueURIErrorMessage + @brief This is the error message the server will respond with if the continue URL provided in + the request is invalid. + */ +static NSString *const kInvalidContinueURIErrorMessage = @"INVALID_CONTINUE_URI"; + +/** @var kMissingContinueURIErrorMessage + @brief This is the error message the server will respond with if there was no continue URI + present in a request that required one. + */ +static NSString *const kMissingContinueURIErrorMessage = @"MISSING_CONTINUE_URI"; + +/** @var kInvalidPhoneNumberErrorMessage + @brief This is the error message the server will respond with if an incorrectly formatted phone + number is provided. + */ +static NSString *const kInvalidPhoneNumberErrorMessage = @"INVALID_PHONE_NUMBER"; + +/** @var kInvalidVerificationCodeErrorMessage + @brief This is the error message the server will respond with if an invalid verification code is + provided. + */ +static NSString *const kInvalidVerificationCodeErrorMessage = @"INVALID_CODE"; + +/** @var kInvalidSessionInfoErrorMessage + @brief This is the error message the server will respond with if an invalid session info + (verification ID) is provided. + */ +static NSString *const kInvalidSessionInfoErrorMessage = @"INVALID_SESSION_INFO"; + +/** @var kSessionExpiredErrorMessage + @brief This is the error message the server will respond with if the SMS code has expired before + it is used. + */ +static NSString *const kSessionExpiredErrorMessage = @"SESSION_EXPIRED"; + +/** @var kMissingOrInvalidNonceErrorMessage + @brief This is the error message the server will respond with if the nonce is missing or + invalid. + */ +static NSString *const kMissingOrInvalidNonceErrorMessage = @"MISSING_OR_INVALID_NONCE"; + +/** @var kMissingAppTokenErrorMessage + @brief This is the error message the server will respond with if the APNS token is missing in a + verifyClient request. + */ +static NSString *const kMissingAppTokenErrorMessage = @"MISSING_IOS_APP_TOKEN"; + +/** @var kMissingAppCredentialErrorMessage + @brief This is the error message the server will respond with if the app token is missing in a + sendVerificationCode request. + */ +static NSString *const kMissingAppCredentialErrorMessage = @"MISSING_APP_CREDENTIAL"; + +/** @var kInvalidAppCredentialErrorMessage + @brief This is the error message the server will respond with if the app credential in a + sendVerificationCode request is invalid. + */ +static NSString *const kInvalidAppCredentialErrorMessage = @"INVALID_APP_CREDENTIAL"; + +/** @var kQuoutaExceededErrorMessage + @brief This is the error message the server will respond with if the quota for SMS text messages + has been exceeded for the project. + */ +static NSString *const kQuoutaExceededErrorMessage = @"QUOTA_EXCEEDED"; + +/** @var kAppNotVerifiedErrorMessage + @brief This is the error message the server will respond with if Firebase could not verify the + app during a phone authentication flow. + */ +static NSString *const kAppNotVerifiedErrorMessage = @"APP_NOT_VERIFIED"; + +/** @var kMissingClientIdentifier + @brief This is the error message the server will respond with if Firebase could not verify the + app during a phone authentication flow when a real phone number is used and app verification + is disabled for testing. + */ +static NSString *const kMissingClientIdentifier = @"MISSING_CLIENT_IDENTIFIER"; + +/** @var kCaptchaCheckFailedErrorMessage + @brief This is the error message the server will respond with if the reCAPTCHA token provided is + invalid. + */ +static NSString *const kCaptchaCheckFailedErrorMessage = @"CAPTCHA_CHECK_FAILED"; + +/** @var kMissingMFAPendingCredentialErrorMessage + @brief This is the error message the server will respond with if the MFA pending credential is + missing. + */ +static NSString *const kMissingMFAPendingCredentialErrorMessage = @"MISSING_MFA_PENDING_CREDENTIAL"; + +/** @var kMissingMFAEnrollmentIDErrorMessage + @brief This is the error message the server will respond with if the MFA enrollment ID is missing. + */ +static NSString *const kMissingMFAEnrollmentIDErrorMessage = @"MISSING_MFA_ENROLLMENT_ID"; + +/** @var kInvalidMFAPendingCredentialErrorMessage + @brief This is the error message the server will respond with if the MFA pending credential is + invalid. + */ +static NSString *const kInvalidMFAPendingCredentialErrorMessage = @"INVALID_MFA_PENDING_CREDENTIAL"; + +/** @var kMFAEnrollmentNotFoundErrorMessage + @brief This is the error message the server will respond with if the MFA enrollment info is not + found. + */ +static NSString *const kMFAEnrollmentNotFoundErrorMessage = @"MFA_ENROLLMENT_NOT_FOUND"; + +/** @var kAdminOnlyOperationErrorMessage + @brief This is the error message the server will respond with if the operation is admin only. + */ +static NSString *const kAdminOnlyOperationErrorMessage = @"ADMIN_ONLY_OPERATION"; + +/** @var kUnverifiedEmailErrorMessage + @brief This is the error message the server will respond with if the email is unverified. + */ +static NSString *const kUnverifiedEmailErrorMessage = @"UNVERIFIED_EMAIL"; + +/** @var kSecondFactorExistsErrorMessage + @brief This is the error message the server will respond with if the second factor already exsists. + */ +static NSString *const kSecondFactorExistsErrorMessage = @"SECOND_FACTOR_EXISTS"; + +/** @var kSecondFactorLimitExceededErrorMessage + @brief This is the error message the server will respond with if the number of second factor + reaches the limit. + */ +static NSString *const kSecondFactorLimitExceededErrorMessage = @"SECOND_FACTOR_LIMIT_EXCEEDED"; + +/** @var kUnsupportedFirstFactorErrorMessage + @brief This is the error message the server will respond with if the first factor doesn't support + MFA. + */ +static NSString *const kUnsupportedFirstFactorErrorMessage = @"UNSUPPORTED_FIRST_FACTOR"; + +/** @var kEmailChangeNeedsVerificationErrorMessage + @brief This is the error message the server will respond with if changing an unverified email. + */ +static NSString *const kEmailChangeNeedsVerificationErrorMessage = + @"EMAIL_CHANGE_NEEDS_VERIFICATION"; + +/** @var kInvalidPendingToken + @brief Generic IDP error codes. + */ +static NSString *const kInvalidPendingToken = @"INVALID_PENDING_TOKEN"; + +/** @var gBackendImplementation + @brief The singleton FIRAuthBackendImplementation instance to use. + */ +static id gBackendImplementation; + +/** @class FIRAuthBackendRPCImplementation + @brief The default RPC-based backend implementation. + */ +@interface FIRAuthBackendRPCImplementation : NSObject + +/** @property RPCIssuer + @brief An instance of FIRAuthBackendRPCIssuer for making RPC requests. Allows the RPC + requests/responses to be easily faked. + */ +@property(nonatomic, strong) id RPCIssuer; + +@end + +@implementation FIRAuthBackend + ++ (id)implementation { + if (!gBackendImplementation) { + gBackendImplementation = [[FIRAuthBackendRPCImplementation alloc] init]; + } + return gBackendImplementation; +} + ++ (void)setBackendImplementation:(id)backendImplementation { + gBackendImplementation = backendImplementation; +} + ++ (void)setDefaultBackendImplementationWithRPCIssuer: + (nullable id)RPCIssuer { + FIRAuthBackendRPCImplementation *defaultImplementation = + [[FIRAuthBackendRPCImplementation alloc] init]; + if (RPCIssuer) { + defaultImplementation.RPCIssuer = RPCIssuer; + } + gBackendImplementation = defaultImplementation; +} + ++ (void)createAuthURI:(FIRCreateAuthURIRequest *)request + callback:(FIRCreateAuthURIResponseCallback)callback { + [[self implementation] createAuthURI:request callback:callback]; +} + ++ (void)getAccountInfo:(FIRGetAccountInfoRequest *)request + callback:(FIRGetAccountInfoResponseCallback)callback { + [[self implementation] getAccountInfo:request callback:callback]; +} + ++ (void)getProjectConfig:(FIRGetProjectConfigRequest *)request + callback:(FIRGetProjectConfigResponseCallback)callback { + [[self implementation] getProjectConfig:request callback:callback]; +} + ++ (void)setAccountInfo:(FIRSetAccountInfoRequest *)request + callback:(FIRSetAccountInfoResponseCallback)callback { + [[self implementation] setAccountInfo:request callback:callback]; +} + ++ (void)verifyAssertion:(FIRVerifyAssertionRequest *)request + callback:(FIRVerifyAssertionResponseCallback)callback { + [[self implementation] verifyAssertion:request callback:callback]; +} + ++ (void)verifyCustomToken:(FIRVerifyCustomTokenRequest *)request + callback:(FIRVerifyCustomTokenResponseCallback)callback { + [[self implementation] verifyCustomToken:request callback:callback]; +} + ++ (void)verifyPassword:(FIRVerifyPasswordRequest *)request + callback:(FIRVerifyPasswordResponseCallback)callback { + [[self implementation] verifyPassword:request callback:callback]; +} + ++ (void)emailLinkSignin:(FIREmailLinkSignInRequest *)request + callback:(FIREmailLinkSigninResponseCallback)callback { + [[self implementation] emailLinkSignin:request callback:callback]; +} + ++ (void)secureToken:(FIRSecureTokenRequest *)request + callback:(FIRSecureTokenResponseCallback)callback { + [[self implementation] secureToken:request callback:callback]; +} + ++ (void)getOOBConfirmationCode:(FIRGetOOBConfirmationCodeRequest *)request + callback:(FIRGetOOBConfirmationCodeResponseCallback)callback { + [[self implementation] getOOBConfirmationCode:request callback:callback]; +} + ++ (void)signUpNewUser:(FIRSignUpNewUserRequest *)request + callback:(FIRSignupNewUserCallback)callback { + [[self implementation] signUpNewUser:request callback:callback]; +} + ++ (void)deleteAccount:(FIRDeleteAccountRequest *)request callback:(FIRDeleteCallBack)callback { + [[self implementation] deleteAccount:request callback:callback]; +} + ++ (void)signInWithGameCenter:(FIRSignInWithGameCenterRequest *)request + callback:(FIRSignInWithGameCenterResponseCallback)callback { + [[self implementation] signInWithGameCenter:request callback:callback]; +} + +#if TARGET_OS_IOS ++ (void)sendVerificationCode:(FIRSendVerificationCodeRequest *)request + callback:(FIRSendVerificationCodeResponseCallback)callback { + [[self implementation] sendVerificationCode:request callback:callback]; +} + ++ (void)verifyPhoneNumber:(FIRVerifyPhoneNumberRequest *)request + callback:(FIRVerifyPhoneNumberResponseCallback)callback { + [[self implementation] verifyPhoneNumber:request callback:callback]; +} + ++ (void)verifyClient:(id)request callback:(FIRVerifyClientResponseCallback)callback { + [[self implementation] verifyClient:request callback:callback]; +} +#endif + ++ (void)resetPassword:(FIRResetPasswordRequest *)request + callback:(FIRResetPasswordCallback)callback { + [[self implementation] resetPassword:request callback:callback]; +} + ++ (NSString *)authUserAgent { + return [NSString stringWithFormat:@"FirebaseAuth.iOS/%s %@", FirebaseAuthVersionStr, + GTMFetcherStandardUserAgentString(nil)]; +} + +@end + +@interface FIRAuthBackendRPCIssuerImplementation : NSObject +@end + +@implementation FIRAuthBackendRPCIssuerImplementation { + /** @var The session fetcher service. + */ + GTMSessionFetcherService *_fetcherService; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _fetcherService = [[GTMSessionFetcherService alloc] init]; + _fetcherService.userAgent = [FIRAuthBackend authUserAgent]; + _fetcherService.callbackQueue = FIRAuthGlobalWorkQueue(); + + // Avoid reusing the session to prevent + // https://github.com/firebase/firebase-ios-sdk/issues/1261 + _fetcherService.reuseSession = NO; + } + return self; +} + +- (void)asyncPostToURLWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + URL:(NSURL *)URL + body:(nullable NSData *)body + contentType:(NSString *)contentType + completionHandler: + (void (^)(NSData *_Nullable, NSError *_Nullable))handler { + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; + NSString *additionalFrameworkMarker = + requestConfiguration.additionalFrameworkMarker ?: kFirebaseAuthCoreFrameworkMarker; + NSString *clientVersion = [NSString + stringWithFormat:@"iOS/FirebaseSDK/%s/%@", FirebaseAuthVersionStr, additionalFrameworkMarker]; + [request setValue:clientVersion forHTTPHeaderField:kClientVersionHeader]; + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; + [request setValue:bundleID forHTTPHeaderField:kIosBundleIdentifierHeader]; + + NSArray *preferredLocalizations = [NSBundle mainBundle].preferredLocalizations; + if (preferredLocalizations.count) { + NSString *acceptLanguage = preferredLocalizations.firstObject; + [request setValue:acceptLanguage forHTTPHeaderField:@"Accept-Language"]; + } + NSString *languageCode = requestConfiguration.languageCode; + if (languageCode.length) { + [request setValue:languageCode forHTTPHeaderField:kFirebaseLocalHeader]; + } + GTMSessionFetcher *fetcher = [_fetcherService fetcherWithRequest:request]; + fetcher.bodyData = body; + [fetcher beginFetchWithCompletionHandler:handler]; +} + +@end + +@implementation FIRAuthBackendRPCImplementation + +- (instancetype)init { + self = [super init]; + if (self) { + _RPCIssuer = [[FIRAuthBackendRPCIssuerImplementation alloc] init]; + } + return self; +} + +- (void)createAuthURI:(FIRCreateAuthURIRequest *)request + callback:(FIRCreateAuthURIResponseCallback)callback { + FIRCreateAuthURIResponse *response = [[FIRCreateAuthURIResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)getAccountInfo:(FIRGetAccountInfoRequest *)request + callback:(FIRGetAccountInfoResponseCallback)callback { + FIRGetAccountInfoResponse *response = [[FIRGetAccountInfoResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)getProjectConfig:(FIRGetProjectConfigRequest *)request + callback:(FIRGetProjectConfigResponseCallback)callback { + FIRGetProjectConfigResponse *response = [[FIRGetProjectConfigResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)setAccountInfo:(FIRSetAccountInfoRequest *)request + callback:(FIRSetAccountInfoResponseCallback)callback { + FIRSetAccountInfoResponse *response = [[FIRSetAccountInfoResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)verifyAssertion:(FIRVerifyAssertionRequest *)request + callback:(FIRVerifyAssertionResponseCallback)callback { + FIRVerifyAssertionResponse *response = [[FIRVerifyAssertionResponse alloc] init]; + [self + postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + if (!response.IDToken && response.MFAInfo) { +#if TARGET_OS_IOS + NSMutableArray *multiFactorInfo = [NSMutableArray array]; + for (FIRAuthProtoMFAEnrollment *MFAEnrollment in response.MFAInfo) { + FIRPhoneMultiFactorInfo *info = + [[FIRPhoneMultiFactorInfo alloc] initWithProto:MFAEnrollment]; + [multiFactorInfo addObject:info]; + } + NSError *multiFactorRequiredError = [FIRAuthErrorUtils + secondFactorRequiredErrorWithPendingCredential:response.MFAPendingCredential + hints:multiFactorInfo]; + callback(nil, multiFactorRequiredError); +#endif + } else { + callback(response, nil); + } + } + }]; +} + +- (void)verifyCustomToken:(FIRVerifyCustomTokenRequest *)request + callback:(FIRVerifyCustomTokenResponseCallback)callback { + FIRVerifyCustomTokenResponse *response = [[FIRVerifyCustomTokenResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)verifyPassword:(FIRVerifyPasswordRequest *)request + callback:(FIRVerifyPasswordResponseCallback)callback { + FIRVerifyPasswordResponse *response = [[FIRVerifyPasswordResponse alloc] init]; + [self + postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + if (!response.IDToken && response.MFAInfo) { +#if TARGET_OS_IOS + NSMutableArray *multiFactorInfo = [NSMutableArray array]; + for (FIRAuthProtoMFAEnrollment *MFAEnrollment in response.MFAInfo) { + FIRPhoneMultiFactorInfo *info = + [[FIRPhoneMultiFactorInfo alloc] initWithProto:MFAEnrollment]; + [multiFactorInfo addObject:info]; + } + NSError *multiFactorRequiredError = [FIRAuthErrorUtils + secondFactorRequiredErrorWithPendingCredential:response.MFAPendingCredential + hints:multiFactorInfo]; + callback(nil, multiFactorRequiredError); +#endif + } else { + callback(response, nil); + } + } + }]; +} + +- (void)emailLinkSignin:(FIREmailLinkSignInRequest *)request + callback:(FIREmailLinkSigninResponseCallback)callback { + FIREmailLinkSignInResponse *response = [[FIREmailLinkSignInResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)secureToken:(FIRSecureTokenRequest *)request + callback:(FIRSecureTokenResponseCallback)callback { + FIRSecureTokenResponse *response = [[FIRSecureTokenResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)getOOBConfirmationCode:(FIRGetOOBConfirmationCodeRequest *)request + callback:(FIRGetOOBConfirmationCodeResponseCallback)callback { + FIRGetOOBConfirmationCodeResponse *response = [[FIRGetOOBConfirmationCodeResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)signUpNewUser:(FIRSignUpNewUserRequest *)request + callback:(FIRSignupNewUserCallback)callback { + FIRSignUpNewUserResponse *response = [[FIRSignUpNewUserResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, nil); + } + }]; +} + +- (void)deleteAccount:(FIRDeleteAccountRequest *)request callback:(FIRDeleteCallBack)callback { + FIRDeleteAccountResponse *response = [[FIRDeleteAccountResponse alloc] init]; + [self postWithRequest:request response:response callback:callback]; +} + +#if TARGET_OS_IOS +- (void)sendVerificationCode:(FIRSendVerificationCodeRequest *)request + callback:(FIRSendVerificationCodeResponseCallback)callback { + FIRSendVerificationCodeResponse *response = [[FIRSendVerificationCodeResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + } else { + callback(response, error); + } + }]; +} + +- (void)verifyPhoneNumber:(FIRVerifyPhoneNumberRequest *)request + callback:(FIRVerifyPhoneNumberResponseCallback)callback { + FIRVerifyPhoneNumberResponse *response = [[FIRVerifyPhoneNumberResponse alloc] init]; + [self + postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + return; + } + // Check whether or not the successful response is actually the special case phone + // auth flow that returns a temporary proof and phone number. + if (response.phoneNumber.length && response.temporaryProof.length) { + FIRPhoneAuthCredential *credential = + [[FIRPhoneAuthCredential alloc] initWithTemporaryProof:response.temporaryProof + phoneNumber:response.phoneNumber + providerID:FIRPhoneAuthProviderID]; + callback(nil, [FIRAuthErrorUtils credentialAlreadyInUseErrorWithMessage:nil + credential:credential + email:nil]); + return; + } + callback(response, nil); + }]; +} + +- (void)verifyClient:(id)request callback:(FIRVerifyClientResponseCallback)callback { + FIRVerifyClientResponse *response = [[FIRVerifyClientResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + return; + } + callback(response, nil); + }]; +} +#endif + +- (void)resetPassword:(FIRResetPasswordRequest *)request + callback:(FIRResetPasswordCallback)callback { + FIRResetPasswordResponse *response = [[FIRResetPasswordResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + callback(nil, error); + return; + } + callback(response, nil); + }]; +} + +- (void)signInWithGameCenter:(FIRSignInWithGameCenterRequest *)request + callback:(FIRSignInWithGameCenterResponseCallback)callback { + FIRSignInWithGameCenterResponse *response = [[FIRSignInWithGameCenterResponse alloc] init]; + [self postWithRequest:request + response:response + callback:^(NSError *error) { + if (error) { + if (callback) { + callback(nil, error); + } + } else { + if (callback) { + callback(response, nil); + } + } + }]; +} + +#pragma mark - Generic RPC handling methods + +/** @fn postWithRequest:response:callback: + @brief Calls the RPC using HTTP POST. + @remarks Possible error responses: + @see FIRAuthInternalErrorCodeRPCRequestEncodingError + @see FIRAuthInternalErrorCodeJSONSerializationError + @see FIRAuthInternalErrorCodeNetworkError + @see FIRAuthInternalErrorCodeUnexpectedErrorResponse + @see FIRAuthInternalErrorCodeUnexpectedResponse + @see FIRAuthInternalErrorCodeRPCResponseDecodingError + @param request The request. + @param response The empty response to be filled. + @param callback The callback for both success and failure. + */ +- (void)postWithRequest:(id)request + response:(id)response + callback:(void (^)(NSError *_Nullable error))callback { + NSError *error; + NSData *bodyData; + if ([request containsPostBody]) { + id postBody = [request unencodedHTTPRequestBodyWithError:&error]; + if (!postBody) { + callback([FIRAuthErrorUtils RPCRequestEncodingErrorWithUnderlyingError:error]); + return; + } + + NSJSONWritingOptions JSONWritingOptions = 0; +#if DEBUG + JSONWritingOptions |= NSJSONWritingPrettyPrinted; +#endif + + if ([NSJSONSerialization isValidJSONObject:postBody]) { + bodyData = [NSJSONSerialization dataWithJSONObject:postBody + options:JSONWritingOptions + error:&error]; + if (!bodyData) { + // This is an untested case. This happens exclusively when there is an error in the + // framework implementation of dataWithJSONObject:options:error:. This shouldn't normally + // occur as isValidJSONObject: should return NO in any case we should encounter an error. + error = [FIRAuthErrorUtils JSONSerializationErrorWithUnderlyingError:error]; + } + } else { + error = [FIRAuthErrorUtils JSONSerializationErrorForUnencodableType]; + } + if (!bodyData) { + callback(error); + return; + } + } + + [_RPCIssuer + asyncPostToURLWithRequestConfiguration:[request requestConfiguration] + URL:[request requestURL] + body:bodyData + contentType:kJSONContentType + completionHandler:^(NSData *data, NSError *error) { + // If there is an error with no body data at all, then this must be a + // network error. + if (error && !data) { + callback([FIRAuthErrorUtils networkErrorWithUnderlyingError:error]); + return; + } + + // Try to decode the HTTP response data which may contain either a + // successful response or error message. + NSError *jsonError; + NSDictionary *dictionary = + [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableLeaves + error:&jsonError]; + if (!dictionary) { + if (error) { + // We have an error, but we couldn't decode the body, so we have no + // additional information other than the raw response and the + // original NSError (the jsonError is infered by the error code + // (FIRAuthErrorCodeUnexpectedHTTPResponse, and is irrelevant.) + callback([FIRAuthErrorUtils + unexpectedErrorResponseWithData:data + underlyingError:error]); + } else { + // This is supposed to be a "successful" response, but we couldn't + // deserialize the body. + callback([FIRAuthErrorUtils unexpectedResponseWithData:data + underlyingError:jsonError]); + } + return; + } + if (![dictionary isKindOfClass:[NSDictionary class]]) { + if (error) { + callback([FIRAuthErrorUtils + unexpectedErrorResponseWithDeserializedResponse:dictionary]); + } else { + callback([FIRAuthErrorUtils + unexpectedResponseWithDeserializedResponse:dictionary]); + } + return; + } + + // At this point we either have an error with successfully decoded + // details in the body, or we have a response which must pass further + // validation before we know it's truly successful. We deal with the + // case where we have an error with successfully decoded error details + // first: + if (error) { + NSDictionary *errorDictionary = dictionary[kErrorKey]; + if ([errorDictionary isKindOfClass:[NSDictionary class]]) { + id errorMessage = errorDictionary[kErrorMessageKey]; + if ([errorMessage isKindOfClass:[NSString class]]) { + NSString *errorMessageString = (NSString *)errorMessage; + + // Contruct client error. + NSError *clientError = [[self class] + clientErrorWithServerErrorMessage:errorMessageString + errorDictionary:errorDictionary + response:response]; + if (clientError) { + callback(clientError); + return; + } + } + // Not a message we know, return the message directly. + if (errorMessage) { + NSError *unexpecterErrorResponse = [FIRAuthErrorUtils + unexpectedErrorResponseWithDeserializedResponse: + errorDictionary]; + callback(unexpecterErrorResponse); + return; + } + } + // No error message at all, return the decoded response. + callback([FIRAuthErrorUtils + unexpectedErrorResponseWithDeserializedResponse:dictionary]); + return; + } + + // Finally, we try to populate the response object with the JSON + // values. + if (![response setWithDictionary:dictionary error:&error]) { + callback([FIRAuthErrorUtils + RPCResponseDecodingErrorWithDeserializedResponse:dictionary + underlyingError:error]); + return; + } + // In case returnIDPCredential of a verifyAssertion request is set to + // @YES, the server may return a 200 with a response that may contain a + // server error. + if ([request isKindOfClass:[FIRVerifyAssertionRequest class]]) { + FIRVerifyAssertionRequest *verifyAssertionRequest = + (FIRVerifyAssertionRequest *)request; + if (verifyAssertionRequest.returnIDPCredential) { + NSString *errorMessage = + dictionary[kReturnIDPCredentialErrorMessageKey]; + if ([errorMessage isKindOfClass:[NSString class]]) { + NSString *errorString = (NSString *)errorMessage; + NSError *clientError = + [[self class] clientErrorWithServerErrorMessage:errorString + errorDictionary:@{} + response:response]; + if (clientError) { + callback(clientError); + return; + } + } + } + } + // Success! The response object originally passed in can be used by the + // caller. + callback(nil); + }]; +} + +/** @fn clientErrorWithServerErrorMessage:errorDictionary: + @brief Translates known server errors to client errors. + @param serverErrorMessage The error message from the server. + @param errorDictionary The error part of the response from the server. + @param response The response from the server RPC. + @return A client error, if any. + */ ++ (nullable NSError *)clientErrorWithServerErrorMessage:(NSString *)serverErrorMessage + errorDictionary:(NSDictionary *)errorDictionary + response:(id)response { + NSString *shortErrorMessage = serverErrorMessage; + NSString *serverDetailErrorMessage; + NSRange colonRange = [serverErrorMessage rangeOfString:@":"]; + if (colonRange.location != NSNotFound) { + shortErrorMessage = [serverErrorMessage substringToIndex:colonRange.location]; + shortErrorMessage = + [shortErrorMessage stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + serverDetailErrorMessage = [serverErrorMessage substringFromIndex:colonRange.location + 1]; + serverDetailErrorMessage = [serverDetailErrorMessage + stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + } + + // Delegate the responsibility for constructing the client error to the response object, + // if possible. + SEL clientErrorWithServerErrorMessageSelector = @selector(clientErrorWithShortErrorMessage: + detailErrorMessage:); + if ([response respondsToSelector:clientErrorWithServerErrorMessageSelector]) { + NSError *error = [response clientErrorWithShortErrorMessage:shortErrorMessage + detailErrorMessage:serverDetailErrorMessage]; + if (error) { + return error; + } + } + + if ([shortErrorMessage isEqualToString:kUserNotFoundErrorMessage]) { + return [FIRAuthErrorUtils userNotFoundErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUserDeletedErrorMessage]) { + return [FIRAuthErrorUtils userNotFoundErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidLocalIDErrorMessage]) { + // This case shouldn't be necessary but it is for now: b/27908364 . + return [FIRAuthErrorUtils userNotFoundErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUserTokenExpiredErrorMessage]) { + return [FIRAuthErrorUtils userTokenExpiredErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kTooManyRequestsErrorMessage]) { + return [FIRAuthErrorUtils tooManyRequestsErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidCustomTokenErrorMessage]) { + return [FIRAuthErrorUtils invalidCustomTokenErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kCustomTokenMismatch]) { + return [FIRAuthErrorUtils customTokenMistmatchErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidCredentialErrorMessage] || + [shortErrorMessage isEqualToString:kInvalidPendingToken]) { + return [FIRAuthErrorUtils invalidCredentialErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUserDisabledErrorMessage]) { + return [FIRAuthErrorUtils userDisabledErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kOperationNotAllowedErrorMessage]) { + return [FIRAuthErrorUtils operationNotAllowedErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kPasswordLoginDisabledErrorMessage]) { + return [FIRAuthErrorUtils operationNotAllowedErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kEmailAlreadyInUseErrorMessage]) { + return [FIRAuthErrorUtils emailAlreadyInUseErrorWithEmail:nil]; + } + + if ([shortErrorMessage isEqualToString:kInvalidEmailErrorMessage]) { + return [FIRAuthErrorUtils invalidEmailErrorWithMessage:serverDetailErrorMessage]; + } + + // "INVALID_IDENTIFIER" can be returned by createAuthURI RPC. Considering email addresses are + // currently the only identifiers, we surface the FIRAuthErrorCodeInvalidEmail error code in this + // case. + if ([shortErrorMessage isEqualToString:kInvalidIdentifierErrorMessage]) { + return [FIRAuthErrorUtils invalidEmailErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kWrongPasswordErrorMessage]) { + return [FIRAuthErrorUtils wrongPasswordErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kCredentialTooOldErrorMessage]) { + return [FIRAuthErrorUtils requiresRecentLoginErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidUserTokenErrorMessage]) { + return [FIRAuthErrorUtils invalidUserTokenErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kFederatedUserIDAlreadyLinkedMessage]) { + FIROAuthCredential *credential; + NSString *email; + if ([response isKindOfClass:[FIRVerifyAssertionResponse class]]) { + FIRVerifyAssertionResponse *verifyAssertion = (FIRVerifyAssertionResponse *)response; + credential = [[FIROAuthCredential alloc] initWithVerifyAssertionResponse:verifyAssertion]; + email = verifyAssertion.email; + } + return [FIRAuthErrorUtils credentialAlreadyInUseErrorWithMessage:serverDetailErrorMessage + credential:credential + email:email]; + } + + if ([shortErrorMessage isEqualToString:kWeakPasswordErrorMessagePrefix]) { + return [FIRAuthErrorUtils weakPasswordErrorWithServerResponseReason:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kExpiredActionCodeErrorMessage]) { + return [FIRAuthErrorUtils expiredActionCodeErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidActionCodeErrorMessage]) { + return [FIRAuthErrorUtils invalidActionCodeErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingEmailErrorMessage]) { + return [FIRAuthErrorUtils missingEmailErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidSenderEmailErrorMessage]) { + return [FIRAuthErrorUtils invalidSenderErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidMessagePayloadErrorMessage]) { + return [FIRAuthErrorUtils invalidMessagePayloadErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidRecipientEmailErrorMessage]) { + return [FIRAuthErrorUtils invalidRecipientEmailErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingIosBundleIDErrorMessage]) { + return [FIRAuthErrorUtils missingIosBundleIDErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingAndroidPackageNameErrorMessage]) { + return [FIRAuthErrorUtils missingAndroidPackageNameErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUnauthorizedDomainErrorMessage]) { + return [FIRAuthErrorUtils unauthorizedDomainErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidContinueURIErrorMessage]) { + return [FIRAuthErrorUtils invalidContinueURIErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidProviderIDErrorMessage]) { + return [FIRAuthErrorUtils invalidProviderIDErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidDynamicLinkDomainErrorMessage]) { + return [FIRAuthErrorUtils invalidDynamicLinkDomainErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingContinueURIErrorMessage]) { + return [FIRAuthErrorUtils missingContinueURIErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidPhoneNumberErrorMessage]) { + return [FIRAuthErrorUtils invalidPhoneNumberErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidSessionInfoErrorMessage]) { + return [FIRAuthErrorUtils invalidVerificationIDErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidVerificationCodeErrorMessage]) { + return [FIRAuthErrorUtils invalidVerificationCodeErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kSessionExpiredErrorMessage]) { + return [FIRAuthErrorUtils sessionExpiredErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingAppTokenErrorMessage]) { + return [FIRAuthErrorUtils missingAppTokenErrorWithUnderlyingError:nil]; + } + + if ([shortErrorMessage isEqualToString:kMissingAppCredentialErrorMessage]) { + return [FIRAuthErrorUtils missingAppCredentialWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidAppCredentialErrorMessage]) { + return [FIRAuthErrorUtils invalidAppCredentialWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kQuoutaExceededErrorMessage]) { + return [FIRAuthErrorUtils quotaExceededErrorWithMessage:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kAppNotVerifiedErrorMessage]) { + return [FIRAuthErrorUtils appNotVerifiedErrorWithMessage:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingClientIdentifier]) { + return [FIRAuthErrorUtils missingClientIdentifierErrorWithMessage:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kCaptchaCheckFailedErrorMessage]) { + return [FIRAuthErrorUtils captchaCheckFailedErrorWithMessage:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingOrInvalidNonceErrorMessage]) { + return [FIRAuthErrorUtils missingOrInvalidNonceErrorWithMessage:serverDetailErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingMFAPendingCredentialErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeMissingMultiFactorSession + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMissingMFAEnrollmentIDErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeMissingMultiFactorInfo + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kInvalidMFAPendingCredentialErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeInvalidMultiFactorSession + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kMFAEnrollmentNotFoundErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeMultiFactorInfoNotFound + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kAdminOnlyOperationErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeAdminRestrictedOperation + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUnverifiedEmailErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeUnverifiedEmail + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kSecondFactorExistsErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeSecondFactorAlreadyEnrolled + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kSecondFactorLimitExceededErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeMaximumSecondFactorCountExceeded + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kUnsupportedFirstFactorErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeUnsupportedFirstFactor + message:serverErrorMessage]; + } + + if ([shortErrorMessage isEqualToString:kEmailChangeNeedsVerificationErrorMessage]) { + return [FIRAuthErrorUtils errorWithCode:FIRAuthInternalErrorCodeEmailChangeNeedsVerification + message:serverErrorMessage]; + } + + // In this case we handle an error that might be specified in the underlying errors dictionary, + // the error message in determined based on the @c reason key in the dictionary. + if (errorDictionary[kErrorsKey]) { + // Check for underlying error with reason = keyInvalid; + id underlyingErrors = errorDictionary[kErrorsKey]; + if ([underlyingErrors isKindOfClass:[NSArray class]]) { + NSArray *underlyingErrorsArray = (NSArray *)underlyingErrors; + for (id underlyingError in underlyingErrorsArray) { + if ([underlyingError isKindOfClass:[NSDictionary class]]) { + NSDictionary *underlyingErrorDictionary = (NSDictionary *)underlyingError; + NSString *reason = underlyingErrorDictionary[kReasonKey]; + if ([reason hasPrefix:kInvalidKeyReasonValue]) { + return [FIRAuthErrorUtils invalidAPIKeyError]; + } + if ([reason isEqualToString:kAppNotAuthorizedReasonValue]) { + return [FIRAuthErrorUtils appNotAuthorizedError]; + } + } + } + } + } + return nil; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h new file mode 100644 index 00000000..9ca4f449 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthRequestConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** @protocol FIRAuthRPCRequest + @brief The generic interface for an RPC request needed by @c FIRAuthBackend. + */ +@protocol FIRAuthRPCRequest + +/** @fn requestURL + @brief Gets the request's full URL. + */ +- (NSURL *)requestURL; + +@optional + +/** @fn containsPostBody + @brief Returns whether the request contains a post body or not. Requests without a post body + are get requests. + @remarks The default implementation returns YES. + */ +- (BOOL)containsPostBody; + +/** @fn UnencodedHTTPRequestBodyWithError: + @brief Creates unencoded HTTP body representing the request. + @param error An out field for an error which occurred constructing the request. + @return The HTTP body data representing the request before any encoding, or nil for error. + */ +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error; + +/** @fn requestConfiguration + @brief Obtains the request configurations if available. + @return Returns the request configurations. + */ +- (FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h new file mode 100644 index 00000000..0fe981a6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @protocol FIRAuthRPCResponse + @brief The generic interface for an RPC response needed by @c FIRAuthBackend. + */ +@protocol FIRAuthRPCResponse + +/** @fn setFieldsWithDictionary:error: + @brief Sets the response instance from the decoded JSON response. + @param dictionary The dictionary decoded from HTTP JSON response. + @param error An out field for an error which occurred constructing the request. + @return Whether the operation was successful or not. + */ +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error; + +@optional + +/** @fn clientErrorWithshortErrorMessage:detailErrorMessage + @brief This optional method allows response classes to create client errors given a short error + message and a detail error message from the server. + @param shortErrorMessage The short error message from the server. + @param detailErrorMessage The detailed error message from the server. + @return A client error, if any. + */ +- (nullable NSError *)clientErrorWithShortErrorMessage:(NSString *)shortErrorMessage + detailErrorMessage:(nullable NSString *)detailErrorMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h new file mode 100644 index 00000000..575ee951 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthRequestConfiguration + @brief Defines configurations to be added to a request to Firebase Auth's backend. + */ +@interface FIRAuthRequestConfiguration : NSObject + +/** @property APIKey + @brief The Firebase Auth API key used in the request. + */ +@property(nonatomic, copy, readonly) NSString *APIKey; + +/** @property LanguageCode + @brief The language code used in the request. + */ +@property(nonatomic, copy, nullable) NSString *languageCode; + +/** @property additionalFrameworkMarker + @brief Additional framework marker that will be added as part of the header of every request. + */ +@property(nonatomic, copy, nullable) NSString *additionalFrameworkMarker; + +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithRequestClass:APIKey:authLanguage: + @brief Designated initializer. + @param APIKey The API key to be used in the request. + */ +- (nullable instancetype)initWithAPIKey:(NSString *)APIKey NS_DESIGNATED_INITIALIZER; +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.m new file mode 100644 index 00000000..40996e57 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" + +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthRequestConfiguration + +- (nullable instancetype)initWithAPIKey:(NSString *)APIKey { + self = [super init]; + if (self) { + _APIKey = [APIKey copy]; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h new file mode 100644 index 00000000..f1e55093 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" + +@class FIRAuthRequestConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRIdentityToolkitRequest + @brief Represents a request to an identity toolkit endpoint. + */ +@interface FIRIdentityToolkitRequest : NSObject + +/** @property endpoint + @brief Gets the RPC's endpoint. + */ +@property(nonatomic, copy, readonly) NSString *endpoint; + +/** @property APIKey + @brief Gets the client's API key used for the request. + */ +@property(nonatomic, copy, readonly) NSString *APIKey; + +/** @fn init + @brief Please use initWithEndpoint:APIKey: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithEndpoint:APIKey: + @brief Designated initializer. + @param endpoint The endpoint name. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + useIdentityPlatform:(BOOL)useIdentityPlatform + useStaging:(BOOL)useStaging; + +/** @fn requestURL + @brief Gets the request's full URL. + */ +- (NSURL *)requestURL; + +/** @fn requestConfiguration + @brief Gets the request's configuration. + */ +- (FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.m new file mode 100644 index 00000000..6b7e420f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.m @@ -0,0 +1,110 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const kFirebaseAuthAPIURLFormat = + @"https://%@/identitytoolkit/v3/relyingparty/%@?key=%@"; +static NSString *const kIdentityPlatformAPIURLFormat = @"https://%@/v2/%@?key=%@"; + +static NSString *gAPIHost = @"www.googleapis.com"; + +static NSString *kFirebaseAuthAPIHost = @"www.googleapis.com"; +static NSString *kIdentityPlatformAPIHost = @"identitytoolkit.googleapis.com"; + +static NSString *kFirebaseAuthStagingAPIHost = @"staging-www.sandbox.googleapis.com"; +static NSString *kIdentityPlatformStagingAPIHost = + @"staging-identitytoolkit.sandbox.googleapis.com"; + +@implementation FIRIdentityToolkitRequest { + FIRAuthRequestConfiguration *_requestConfiguration; + + BOOL _useIdentityPlatform; + + BOOL _useStaging; +} + +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super init]; + if (self) { + _APIKey = [requestConfiguration.APIKey copy]; + _endpoint = [endpoint copy]; + _requestConfiguration = requestConfiguration; + _useIdentityPlatform = NO; + _useStaging = NO; + } + return self; +} + +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + useIdentityPlatform:(BOOL)useIdentityPlatform + useStaging:(BOOL)useStaging { + self = [self initWithEndpoint:endpoint requestConfiguration:requestConfiguration]; + if (self) { + _useIdentityPlatform = useIdentityPlatform; + _useStaging = useStaging; + } + return self; +} + +- (BOOL)containsPostBody { + return YES; +} + +- (NSURL *)requestURL { + NSString *apiURLFormat; + NSString *apiHost; + if (_useIdentityPlatform) { + apiURLFormat = kIdentityPlatformAPIURLFormat; + if (_useStaging) { + apiHost = kIdentityPlatformStagingAPIHost; + } else { + apiHost = kIdentityPlatformAPIHost; + } + } else { + apiURLFormat = kFirebaseAuthAPIURLFormat; + if (_useStaging) { + apiHost = kFirebaseAuthStagingAPIHost; + } else { + apiHost = kFirebaseAuthAPIHost; + } + } + NSString *URLString = [NSString stringWithFormat:apiURLFormat, apiHost, _endpoint, _APIKey]; + NSURL *URL = [NSURL URLWithString:URLString]; + return URL; +} + +- (FIRAuthRequestConfiguration *)requestConfiguration { + return _requestConfiguration; +} + +#pragma mark - Internal API for development + ++ (NSString *)host { + return gAPIHost; +} + ++ (void)setHost:(NSString *)host { + gAPIHost = host; +} + +NS_ASSUME_NONNULL_END + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h new file mode 100644 index 00000000..633ffa97 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h @@ -0,0 +1,88 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRCreateAuthURIRequest + @brief Represents the parameters for the createAuthUri endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/createAuthUri + */ +@interface FIRCreateAuthURIRequest : FIRIdentityToolkitRequest + +/** @property identifier + @brief The email or federated ID of the user. + */ +@property(nonatomic, copy) NSString *identifier; + +/** @property continueURI + @brief The URI to which the IDP redirects the user after the federated login flow. + */ +@property(nonatomic, copy) NSString *continueURI; + +/** @property openIDRealm + @brief Optional realm for OpenID protocol. The sub string "scheme://domain:port" of the param + "continueUri" is used if this is not set. + */ +@property(nonatomic, copy, nullable) NSString *openIDRealm; + +/** @property providerID + @brief The IdP ID. For white listed IdPs it's a short domain name e.g. google.com, aol.com, + live.net and yahoo.com. For other OpenID IdPs it's the OP identifier. + */ +@property(nonatomic, copy, nullable) NSString *providerID; + +/** @property clientID + @brief The relying party OAuth client ID. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** @property context + @brief The opaque value used by the client to maintain context info between the authentication + request and the IDP callback. + */ +@property(nonatomic, copy, nullable) NSString *context; + +/** @property appID + @brief The iOS client application's bundle identifier. + */ +@property(nonatomic, copy, nullable) NSString *appID; + +/** @fn initWithEndpoint:requestConfiguration:requestConfiguration. + @brief Please use initWithIdentifier:continueURI:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithIdentifier:continueURI:requestConfiguration: + @brief Designated initializer. + @param identifier The email or federated ID of the user. + @param continueURI The URI to which the IDP redirects the user after the federated login flow. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithIdentifier:(NSString *)identifier + continueURI:(NSString *)continueURI + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.m new file mode 100644 index 00000000..c1a6fc0e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.m @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kCreateAuthURIEndpoint + @brief The "createAuthUri" endpoint. + */ +static NSString *const kCreateAuthURIEndpoint = @"createAuthUri"; + +/** @var kProviderIDKey + @brief The key for the "providerId" value in the request. + */ +static NSString *const kProviderIDKey = @"providerId"; + +/** @var kIdentifierKey + @brief The key for the "identifier" value in the request. + */ +static NSString *const kIdentifierKey = @"identifier"; + +/** @var kContinueURIKey + @brief The key for the "continueUri" value in the request. + */ +static NSString *const kContinueURIKey = @"continueUri"; + +/** @var kOpenIDRealmKey + @brief The key for the "openidRealm" value in the request. + */ +static NSString *const kOpenIDRealmKey = @"openidRealm"; + +/** @var kClientIDKey + @brief The key for the "clientId" value in the request. + */ +static NSString *const kClientIDKey = @"clientId"; + +/** @var kContextKey + @brief The key for the "context" value in the request. + */ +static NSString *const kContextKey = @"context"; + +/** @var kAppIDKey + @brief The key for the "appId" value in the request. + */ +static NSString *const kAppIDKey = @"appId"; + +@implementation FIRCreateAuthURIRequest + +- (nullable instancetype)initWithIdentifier:(NSString *)identifier + continueURI:(NSString *)continueURI + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kCreateAuthURIEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _identifier = [identifier copy]; + _continueURI = [continueURI copy]; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = + [@{kIdentifierKey : _identifier, kContinueURIKey : _continueURI} mutableCopy]; + if (_providerID) { + postBody[kProviderIDKey] = _providerID; + } + if (_openIDRealm) { + postBody[kOpenIDRealmKey] = _openIDRealm; + } + if (_clientID) { + postBody[kClientIDKey] = _clientID; + } + if (_context) { + postBody[kContextKey] = _context; + } + if (_appID) { + postBody[kAppIDKey] = _appID; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h new file mode 100644 index 00000000..79c5ea7d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRCreateAuthURIResponse + @brief Represents the parameters for the createAuthUri endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/createAuthUri + */ +@interface FIRCreateAuthURIResponse : NSObject + +/** @property authUri + @brief The URI used by the IDP to authenticate the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *authURI; + +/** @property registered + @brief Whether the user is registered if the identifier is an email. + */ +@property(nonatomic, assign, readonly) BOOL registered; + +/** @property providerId + @brief The provider ID of the auth URI. + */ +@property(nonatomic, strong, readonly, nullable) NSString *providerID; + +/** @property forExistingProvider + @brief True if the authUri is for user's existing provider. + */ +@property(nonatomic, assign, readonly) BOOL forExistingProvider; + +/** @property allProviders + @brief A list of provider IDs the passed @c identifier could use to sign in with. + */ +@property(nonatomic, copy, readonly, nullable) NSArray *allProviders; + +/** @property signinMethods + @brief A list of sign-in methods available for the passed @c identifier. + */ +@property(nonatomic, copy, readonly, nullable) NSArray *signinMethods; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.m new file mode 100644 index 00000000..bf422c9c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRCreateAuthURIResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _providerID = [dictionary[@"providerId"] copy]; + _authURI = [dictionary[@"authUri"] copy]; + _registered = [dictionary[@"registered"] boolValue]; + _forExistingProvider = [dictionary[@"forExistingProvider"] boolValue]; + _allProviders = [dictionary[@"allProviders"] copy]; + _signinMethods = [dictionary[@"signinMethods"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h new file mode 100644 index 00000000..b6b6e404 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRDeleteAccountRequest + @brief Represents the parameters for the deleteAccount endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/deleteAccount + */ +@interface FIRDeleteAccountRequest : FIRIdentityToolkitRequest + +/** @fn initWithEndpoint:requestConfiguration:requestConfiguration. + @brief Please use initWitLocalID:accessToken:requestConfiguration instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWitLocalID:accessToken:requestConfiguration. + @brief Designated initializer. + @param localID The local ID. + @param accessToken The access token. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWitLocalID:(NSString *)localID + accessToken:(NSString *)accessToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.m new file mode 100644 index 00000000..8bc6c52e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.m @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kCreateAuthURIEndpoint + @brief The "deleteAccount" endpoint. + */ +static NSString *const kDeleteAccountEndpoint = @"deleteAccount"; + +/** @var kIDTokenKey + @brief The key for the "idToken" value in the request. This is actually the STS Access Token, + despite it's confusing (backwards compatiable) parameter name. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kLocalIDKey + @brief The key for the "localID" value in the request. + */ +static NSString *const kLocalIDKey = @"localId"; + +@implementation FIRDeleteAccountRequest { + /** @var _accessToken + @brief The STS Access Token of the authenticated user. + */ + NSString *_accessToken; + + /** @var _localID + @brief The localID of the user. + */ + NSString *_localID; +} + +- (nullable instancetype)initWitLocalID:(NSString *)localID + accessToken:(NSString *)accessToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kDeleteAccountEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _localID = [localID copy]; + _accessToken = [accessToken copy]; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + postBody[kIDTokenKey] = _accessToken; + postBody[kLocalIDKey] = _localID; + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h new file mode 100644 index 00000000..bc4d0d99 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRDeleteAccountResponse + @brief Represents the response from the deleteAccount endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/deleteAccount + */ +@interface FIRDeleteAccountResponse : NSObject +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.m new file mode 100644 index 00000000..fba1b6b0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.m @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRDeleteAccountResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h new file mode 100644 index 00000000..752ffb4b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIREmailLinkSignInRequest + @brief Represents the parameters for the emailLinkSignin endpoint. + */ +@interface FIREmailLinkSignInRequest : FIRIdentityToolkitRequest + +#pragma mark - Components of "postBody" + +/** @property email + @brief The email identifier used to complete the email link sign-in. + */ +@property(nonatomic, copy, readonly) NSString *email; + +/** @property oobCode + @brief The OOB code used to complete the email link sign-in flow. + */ +@property(nonatomic, copy, readonly) NSString *oobCode; + +/** @property IDToken + @brief The ID Token code potentially used to complete the email link sign-in flow. + */ +@property(nonatomic, copy) NSString *IDToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithProviderID:requestConfifuration instead. + */ +- (instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration NS_UNAVAILABLE; + +/** @fn initWithProviderID:requestConfifuration + @brief Designated initializer. + @param email The email identifier used to complete hte email link sign-in flow. + @param oobCode The OOB code used to complete the email link sign-in flow. + @param requestConfiguration An object containing configurations to be added to the request. + + */ +- (instancetype)initWithEmail:(NSString *)email + oobCode:(NSString *)oobCode + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.m new file mode 100644 index 00000000..dc5b512e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kEmailLinkSigninEndpoint + @brief The "EmailLinkSignin" endpoint. + */ +static NSString *const kEmailLinkSigninEndpoint = @"emailLinkSignin"; + +/** @var kEmailKey + @brief The key for the "identifier" value in the request. + */ +static NSString *const kEmailKey = @"email"; + +/** @var kEmailLinkKey + @brief The key for the "emailLink" value in the request. + */ +static NSString *const kOOBCodeKey = @"oobCode"; + +/** @var kIDTokenKey + @brief The key for the "IDToken" value in the request. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kPostBodyKey + @brief The key for the "postBody" value in the request. + */ +static NSString *const kPostBodyKey = @"postBody"; + +@implementation FIREmailLinkSignInRequest + +- (instancetype)initWithEmail:(NSString *)email + oobCode:(NSString *)oobCode + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kEmailLinkSigninEndpoint + requestConfiguration:requestConfiguration]; + if (self) { + _email = email; + _oobCode = oobCode; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [@{ + kEmailKey : _email, + kOOBCodeKey : _oobCode, + } mutableCopy]; + + if (_IDToken) { + postBody[kIDTokenKey] = _IDToken; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h new file mode 100644 index 00000000..c12b0aa8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyAssertionResponse + @brief Represents the response from the emailLinkSignin endpoint. + */ +@interface FIREmailLinkSignInResponse : NSObject + +/** @property IDToken + @brief The ID token in the email link sign-in response. + */ +@property(nonatomic, copy, readonly) NSString *IDToken; + +/** @property email + @brief The email returned by the IdP. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property refreshToken + @brief The refreshToken returned by the server. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property isNewUser + @brief Flag indicating that the user signing in is a new user and not a returning user. + */ +@property(nonatomic, assign) BOOL isNewUser; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.m new file mode 100644 index 00000000..9f125e14 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.m @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIREmailLinkSignInResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _email = [dictionary[@"email"] copy]; + _IDToken = [dictionary[@"idToken"] copy]; + _isNewUser = [dictionary[@"isNewUser"] boolValue]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h new file mode 100644 index 00000000..7d78500a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGetAccountInfoRequest + @brief Represents the parameters for the getAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/getAccountInfo + */ +@interface FIRGetAccountInfoRequest : FIRIdentityToolkitRequest + +/** @property accessToken + @brief The STS Access Token for the authenticated user. + */ +@property(nonatomic, copy) NSString *accessToken; + +/** @fn initWithEndpoint:requestConfiguration:requestConfiguration + @brief Please use initWithAccessToken:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithAccessToken:requestConfiguration + @brief Designated initializer. + @param accessToken The Access Token of the authenticated user. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithAccessToken:(NSString *)accessToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.m new file mode 100644 index 00000000..db86f934 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.m @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kGetAccountInfoEndpoint + @brief The "getAccountInfo" endpoint. + */ +static NSString *const kGetAccountInfoEndpoint = @"getAccountInfo"; + +/** @var kIDTokenKey + @brief The key for the "idToken" value in the request. This is actually the STS Access Token, + despite it's confusing (backwards compatiable) parameter name. + */ +static NSString *const kIDTokenKey = @"idToken"; + +@implementation FIRGetAccountInfoRequest + +- (nullable instancetype)initWithAccessToken:(NSString *)accessToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kGetAccountInfoEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _accessToken = [accessToken copy]; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + return @{kIDTokenKey : _accessToken}; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h new file mode 100644 index 00000000..14e7f88c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h @@ -0,0 +1,158 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGetAccountInfoResponseProviderUserInfo + @brief Represents the provider user info part of the response from the getAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/getAccountInfo + */ +@interface FIRGetAccountInfoResponseProviderUserInfo : NSObject + +/** @property providerID + @brief The ID of the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *providerID; + +/** @property displayName + @brief The user's display name at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property photoURL + @brief The user's photo URL at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSURL *photoURL; + +/** @property federatedID + @brief The user's identifier at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *federatedID; + +/** @property email + @brief The user's email at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property phoneNumber + @brief A phone number associated with the user. + */ +@property(nonatomic, readonly, nullable) NSString *phoneNumber; + +/** @fn init + @brief Please use initWithDictionary: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithAPIKey: + @brief Designated initializer. + @param dictionary The provider user info data from endpoint. + */ +- (instancetype)initWithDictionary:(NSDictionary *)dictionary NS_DESIGNATED_INITIALIZER; + +@end + +/** @class FIRGetAccountInfoResponseUser + @brief Represents the firebase user info part of the response from the getAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/getAccountInfo + */ +@interface FIRGetAccountInfoResponseUser : NSObject + +/** @property localID + @brief The ID of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *localID; + +/** @property email + @brief The email or the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property emailVerified + @brief Whether the email has been verified. + */ +@property(nonatomic, assign, readonly) BOOL emailVerified; + +/** @property displayName + @brief The display name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property photoURL + @brief The user's photo URL. + */ +@property(nonatomic, strong, readonly, nullable) NSURL *photoURL; + +/** @property creationDate + @brief The user's creation date. + */ +@property(nonatomic, strong, readonly, nullable) NSDate *creationDate; + +/** @property lastSignInDate + @brief The user's last login date. + */ +@property(nonatomic, strong, readonly, nullable) NSDate *lastLoginDate; + +/** @property providerUserInfo + @brief The user's profiles at the associated identity providers. + */ +@property(nonatomic, strong, readonly, nullable) + NSArray *providerUserInfo; + +/** @property passwordHash + @brief Information about user's password. + @remarks This is not necessarily the hash of user's actual password. + */ +@property(nonatomic, strong, readonly, nullable) NSString *passwordHash; + +/** @property phoneNumber + @brief A phone number associated with the user. + */ +@property(nonatomic, readonly, nullable) NSString *phoneNumber; + +@property(nonatomic, strong, readonly, nullable) + NSArray *MFAEnrollments; + +/** @fn init + @brief Please use initWithDictionary: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithAPIKey: + @brief Designated initializer. + @param dictionary The provider user info data from endpoint. + */ +- (instancetype)initWithDictionary:(NSDictionary *)dictionary NS_DESIGNATED_INITIALIZER; + +@end + +/** @class FIRGetAccountInfoResponse + @brief Represents the response from the setAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/getAccountInfo + */ +@interface FIRGetAccountInfoResponse : NSObject + +/** @property providerUserInfo + @brief The requested users' profiles. + */ +@property(nonatomic, strong, readonly, nullable) NSArray *users; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.m new file mode 100644 index 00000000..6b812bd9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.m @@ -0,0 +1,117 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h" + +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kErrorKey + @brief The key for the "error" value in JSON responses from the server. + */ +static NSString *const kErrorKey = @"error"; + +@implementation FIRGetAccountInfoResponseProviderUserInfo + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _providerID = [dictionary[@"providerId"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + NSString *photoURL = dictionary[@"photoUrl"]; + if (photoURL) { + _photoURL = [NSURL URLWithString:photoURL]; + } + _federatedID = [dictionary[@"federatedId"] copy]; + _email = [dictionary[@"email"] copy]; + _phoneNumber = [dictionary[@"phoneNumber"] copy]; + } + return self; +} + +@end + +@implementation FIRGetAccountInfoResponseUser + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + NSArray *providerUserInfoData = dictionary[@"providerUserInfo"]; + if (providerUserInfoData) { + NSMutableArray *providerUserInfoArray = + [NSMutableArray arrayWithCapacity:providerUserInfoData.count]; + for (NSDictionary *dictionary in providerUserInfoData) { + [providerUserInfoArray addObject:[[FIRGetAccountInfoResponseProviderUserInfo alloc] + initWithDictionary:dictionary]]; + } + _providerUserInfo = [providerUserInfoArray copy]; + } + _localID = [dictionary[@"localId"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + _email = [dictionary[@"email"] copy]; + NSString *photoURL = dictionary[@"photoUrl"]; + if (photoURL) { + _photoURL = [NSURL URLWithString:photoURL]; + } + if ([dictionary[@"createdAt"] isKindOfClass:[NSString class]]) { + // Divide by 1000 in order to convert miliseconds to seconds. + NSTimeInterval creationDateTimeInterval = [dictionary[@"createdAt"] doubleValue] / 1000; + _creationDate = [NSDate dateWithTimeIntervalSince1970:creationDateTimeInterval]; + } + if ([dictionary[@"lastLoginAt"] isKindOfClass:[NSString class]]) { + // Divide by 1000 in order to convert miliseconds to seconds + NSTimeInterval creationDateTimeInterval = [dictionary[@"lastLoginAt"] doubleValue] / 1000; + _lastLoginDate = [NSDate dateWithTimeIntervalSince1970:creationDateTimeInterval]; + } + _emailVerified = [dictionary[@"emailVerified"] boolValue]; + _passwordHash = [dictionary[@"passwordHash"] copy]; + _phoneNumber = [dictionary[@"phoneNumber"] copy]; + NSArray *MFAEnrollmentData = dictionary[@"mfaInfo"]; + if (MFAEnrollmentData) { + NSMutableArray *MFAEnrollments = + [NSMutableArray arrayWithCapacity:MFAEnrollmentData.count]; + for (NSDictionary *dictionary in MFAEnrollmentData) { + [MFAEnrollments + addObject:[[FIRAuthProtoMFAEnrollment alloc] initWithDictionary:dictionary]]; + } + _MFAEnrollments = [MFAEnrollments copy]; + } + } + return self; +} + +@end + +@implementation FIRGetAccountInfoResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + NSArray *usersData = dictionary[@"users"]; + // The client side never sends a getAccountInfo request with multiple localID, so only one user + // data is expected in the response. + if (![usersData isKindOfClass:[NSArray class]] || usersData.count != 1) { + if (error) { + *error = [FIRAuthErrorUtils unexpectedResponseWithDeserializedResponse:dictionary]; + } + return NO; + } + _users = @[ [[FIRGetAccountInfoResponseUser alloc] initWithDictionary:usersData.firstObject] ]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h new file mode 100644 index 00000000..dc48a3ed --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h @@ -0,0 +1,178 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +@class FIRActionCodeSettings; + +NS_ASSUME_NONNULL_BEGIN + +/** @enum FIRGetOOBConfirmationCodeRequestType + @brief Types of OOB Confirmation Code requests. + */ +typedef NS_ENUM(NSInteger, FIRGetOOBConfirmationCodeRequestType) { + /** @var FIRGetOOBConfirmationCodeRequestTypePasswordReset + @brief Requests a password reset code. + */ + FIRGetOOBConfirmationCodeRequestTypePasswordReset, + + /** @var FIRGetOOBConfirmationCodeRequestTypeVerifyEmail + @brief Requests an email verification code. + */ + FIRGetOOBConfirmationCodeRequestTypeVerifyEmail, + + /** @var FIRGetOOBConfirmationCodeRequestTypeEmailLink + @brief Requests an email sign-in link. + */ + FIRGetOOBConfirmationCodeRequestTypeEmailLink, + + /** @var FIRGetOOBConfirmationCodeRequestTypeVerifyBeforeUpdateEmail + @brief Requests an verify before update email. + */ + FIRGetOOBConfirmationCodeRequestTypeVerifyBeforeUpdateEmail, +}; + +/** @enum FIRGetOOBConfirmationCodeRequest + @brief Represents the parameters for the getOOBConfirmationCode endpoint. + */ +@interface FIRGetOOBConfirmationCodeRequest : FIRIdentityToolkitRequest + +/** @property requestType + @brief The types of OOB Confirmation Code to request. + */ +@property(nonatomic, assign, readonly) FIRGetOOBConfirmationCodeRequestType requestType; + +/** @property email + @brief The email of the user. + @remarks For password reset. + */ +@property(nonatomic, copy, nullable, readonly) NSString *email; + +/** @property updatedEmail + @brief The new email to be updated. + @remarks For verifyBeforeUpdateEmail. + */ +@property(nonatomic, copy, nullable, readonly) NSString *updatedEmail; + +/** @property accessToken + @brief The STS Access Token of the authenticated user. + @remarks For email change. + */ +@property(nonatomic, copy, nullable, readonly) NSString *accessToken; + +/** @property continueURL + @brief This URL represents the state/Continue URL in the form of a universal link. + */ +@property(nonatomic, copy, nullable, readonly) NSString *continueURL; + +/** @property iOSBundleID + @brief The iOS bundle Identifier, if available. + */ +@property(nonatomic, copy, nullable, readonly) NSString *iOSBundleID; + +/** @property androidPackageName + @brief The Android package name, if available. + */ +@property(nonatomic, copy, nullable, readonly) NSString *androidPackageName; + +/** @property androidMinimumVersion + @brief The minimum Android version supported, if available. + */ +@property(nonatomic, copy, nullable, readonly) NSString *androidMinimumVersion; + +/** @property androidInstallIfNotAvailable + @brief Indicates whether or not the Android app should be installed if not already available. + */ +@property(nonatomic, assign, readonly) BOOL androidInstallApp; + +/** @property handleCodeInApp + @brief Indicates whether the action code link will open the app directly or after being + redirected from a Firebase owned web widget. + */ +@property(assign, nonatomic) BOOL handleCodeInApp; + +/** @property dynamicLinkDomain + @brief The Firebase Dynamic Link domain used for out of band code flow. + */ +@property(copy, nonatomic, nullable) NSString *dynamicLinkDomain; + +/** @fn passwordResetRequestWithEmail:actionCodeSettings:requestConfiguration: + @brief Creates a password reset request. + @param email The user's email address. + @param actionCodeSettings An object of FIRActionCodeSettings which specifies action code + settings to be applied to the password reset request. + @param requestConfiguration An object containing configurations to be added to the request. + @return A password reset request. + */ ++ (nullable FIRGetOOBConfirmationCodeRequest *) + passwordResetRequestWithEmail:(NSString *)email + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn verifyEmailRequestWithAccessToken:actionCodeSettings:requestConfiguration: + @brief Creates a password reset request. + @param accessToken The user's STS Access Token. + @param actionCodeSettings An object of FIRActionCodeSettings which specifies action code + settings to be applied to the email verification request. + @param requestConfiguration An object containing configurations to be added to the request. + @return A password reset request. + */ ++ (nullable FIRGetOOBConfirmationCodeRequest *) + verifyEmailRequestWithAccessToken:(NSString *)accessToken + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn signInWithEmailLinkRequest:actionCodeSettings:requestConfiguration: + @brief Creates a sign-in with email link. + @param email The user's email address. + @param actionCodeSettings An object of FIRActionCodeSettings which specifies action code + settings to be applied to the email sign-in link. + @param requestConfiguration An object containing configurations to be added to the request. + @return An email sign-in link request. + */ ++ (nullable FIRGetOOBConfirmationCodeRequest *) + signInWithEmailLinkRequest:(NSString *)email + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn verifyBeforeUpdateEmailWithAccessToken:newEmail:actionCodeSettings:requestConfiguration: + @brief Creates a verifyBeforeUpdateEmail request. + @param accessToken The user's STS Access Token. + @param newEmail The user's email address to be updated. + @param actionCodeSettings An object of FIRActionCodeSettings which specifies action code + settings to be applied to the password reset request. + @param requestConfiguration An object containing configurations to be added to the request. + @return A verifyBeforeUpdateEmail request. + */ ++ (nullable FIRGetOOBConfirmationCodeRequest *) + verifyBeforeUpdateEmailWithAccessToken:(NSString *)accessToken + newEmail:(NSString *)newEmail + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn init + @brief Please use a factory method. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.m new file mode 100644 index 00000000..cbcde818 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.m @@ -0,0 +1,288 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h" + +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kEndpoint + @brief The getOobConfirmationCode endpoint name. + */ +static NSString *const kGetOobConfirmationCodeEndpoint = @"getOobConfirmationCode"; + +/** @var kRequestTypeKey + @brief The name of the required "requestType" property in the request. + */ +static NSString *const kRequestTypeKey = @"requestType"; + +/** @var kEmailKey + @brief The name of the "email" property in the request. + */ +static NSString *const kEmailKey = @"email"; + +/** @var kNewEmailKey + @brief The name of the "newEmail" property in the request. + */ +static NSString *const kNewEmailKey = @"newEmail"; + +/** @var kIDTokenKey + @brief The key for the "idToken" value in the request. This is actually the STS Access Token, + despite it's confusing (backwards compatiable) parameter name. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kContinueURLKey + @brief The key for the "continue URL" value in the request. + */ +static NSString *const kContinueURLKey = @"continueUrl"; + +/** @var kIosBundeIDKey + @brief The key for the "iOS Bundle Identifier" value in the request. + */ +static NSString *const kIosBundleIDKey = @"iOSBundleId"; + +/** @var kAndroidPackageNameKey + @brief The key for the "Android Package Name" value in the request. + */ +static NSString *const kAndroidPackageNameKey = @"androidPackageName"; + +/** @var kAndroidInstallAppKey + @brief The key for the request parameter indicating whether the android app should be installed + or not. + */ +static NSString *const kAndroidInstallAppKey = @"androidInstallApp"; + +/** @var kAndroidMinimumVersionKey + @brief The key for the "minimum Android version supported" value in the request. + */ +static NSString *const kAndroidMinimumVersionKey = @"androidMinimumVersion"; + +/** @var kCanHandleCodeInAppKey + @brief The key for the request parameter indicating whether the action code can be handled in + the app or not. + */ +static NSString *const kCanHandleCodeInAppKey = @"canHandleCodeInApp"; + +/** @var kDynamicLinkDomainKey + @brief The key for the "dynamic link domain" value in the request. + */ +static NSString *const kDynamicLinkDomainKey = @"dynamicLinkDomain"; + +/** @var kPasswordResetRequestTypeValue + @brief The value for the "PASSWORD_RESET" request type. + */ +static NSString *const kPasswordResetRequestTypeValue = @"PASSWORD_RESET"; + +/** @var kEmailLinkSignInTypeValue + @brief The value for the "EMAIL_SIGNIN" request type. + */ +static NSString *const kEmailLinkSignInTypeValue = @"EMAIL_SIGNIN"; + +/** @var kVerifyEmailRequestTypeValue + @brief The value for the "VERIFY_EMAIL" request type. + */ +static NSString *const kVerifyEmailRequestTypeValue = @"VERIFY_EMAIL"; + +/** @var kVerifyBeforeUpdateEmailRequestTypeValue + @brief The value for the "VERIFY_AND_CHANGE_EMAIL" request type. + */ +static NSString *const kVerifyBeforeUpdateEmailRequestTypeValue = @"VERIFY_AND_CHANGE_EMAIL"; + +@interface FIRGetOOBConfirmationCodeRequest () + +/** @fn initWithRequestType:email:APIKey: + @brief Designated initializer. + @param requestType The types of OOB Confirmation Code to request. + @param email The email of the user. + @param newEmail The email of the user to be updated. + @param accessToken The STS Access Token of the currently signed in user. + @param actionCodeSettings An object of FIRActionCodeSettings which specifies action code + settings to be applied to the OOB code request. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithRequestType:(FIRGetOOBConfirmationCodeRequestType)requestType + email:(nullable NSString *)email + newEmail:(nullable NSString *)newEmail + accessToken:(nullable NSString *)accessToken + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +@implementation FIRGetOOBConfirmationCodeRequest + +/** @var requestTypeStringValueForRequestType: + @brief Returns the string equivilent for an @c FIRGetOOBConfirmationCodeRequestType value. + */ ++ (NSString *)requestTypeStringValueForRequestType: + (FIRGetOOBConfirmationCodeRequestType)requestType { + switch (requestType) { + case FIRGetOOBConfirmationCodeRequestTypePasswordReset: + return kPasswordResetRequestTypeValue; + case FIRGetOOBConfirmationCodeRequestTypeVerifyEmail: + return kVerifyEmailRequestTypeValue; + case FIRGetOOBConfirmationCodeRequestTypeEmailLink: + return kEmailLinkSignInTypeValue; + case FIRGetOOBConfirmationCodeRequestTypeVerifyBeforeUpdateEmail: + return kVerifyBeforeUpdateEmailRequestTypeValue; + // No default case so that we get a compiler warning if a new value was added to the enum. + } +} + ++ (nullable FIRGetOOBConfirmationCodeRequest *) + passwordResetRequestWithEmail:(NSString *)email + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + return [[self alloc] initWithRequestType:FIRGetOOBConfirmationCodeRequestTypePasswordReset + email:email + newEmail:nil + accessToken:nil + actionCodeSettings:actionCodeSettings + requestConfiguration:requestConfiguration]; +} + ++ (nullable FIRGetOOBConfirmationCodeRequest *) + verifyEmailRequestWithAccessToken:(NSString *)accessToken + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + return [[self alloc] initWithRequestType:FIRGetOOBConfirmationCodeRequestTypeVerifyEmail + email:nil + newEmail:nil + accessToken:accessToken + actionCodeSettings:actionCodeSettings + requestConfiguration:requestConfiguration]; +} + ++ (nullable FIRGetOOBConfirmationCodeRequest *) + signInWithEmailLinkRequest:(NSString *)email + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + return [[self alloc] initWithRequestType:FIRGetOOBConfirmationCodeRequestTypeEmailLink + email:email + newEmail:nil + accessToken:nil + actionCodeSettings:actionCodeSettings + requestConfiguration:requestConfiguration]; +} + ++ (nullable FIRGetOOBConfirmationCodeRequest *) + verifyBeforeUpdateEmailWithAccessToken:(NSString *)accessToken + newEmail:(NSString *)newEmail + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + return + [[self alloc] initWithRequestType:FIRGetOOBConfirmationCodeRequestTypeVerifyBeforeUpdateEmail + email:nil + newEmail:newEmail + accessToken:accessToken + actionCodeSettings:actionCodeSettings + requestConfiguration:requestConfiguration]; +} + +- (nullable instancetype)initWithRequestType:(FIRGetOOBConfirmationCodeRequestType)requestType + email:(nullable NSString *)email + newEmail:(nullable NSString *)newEmail + accessToken:(nullable NSString *)accessToken + actionCodeSettings:(nullable FIRActionCodeSettings *)actionCodeSettings + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kGetOobConfirmationCodeEndpoint + requestConfiguration:requestConfiguration]; + if (self) { + _requestType = requestType; + _email = email; + _updatedEmail = newEmail; + _accessToken = accessToken; + _continueURL = actionCodeSettings.URL.absoluteString; + _iOSBundleID = actionCodeSettings.iOSBundleID; + _androidPackageName = actionCodeSettings.androidPackageName; + _androidMinimumVersion = actionCodeSettings.androidMinimumVersion; + _androidInstallApp = actionCodeSettings.androidInstallIfNotAvailable; + _handleCodeInApp = actionCodeSettings.handleCodeInApp; + _dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *body = + [@{kRequestTypeKey : [[self class] requestTypeStringValueForRequestType:_requestType]} + mutableCopy]; + + // For password reset requests, we only need an email address in addition to the already required + // fields. + if (_requestType == FIRGetOOBConfirmationCodeRequestTypePasswordReset) { + body[kEmailKey] = _email; + } + + // For verify email requests, we only need an STS Access Token in addition to the already required + // fields. + if (_requestType == FIRGetOOBConfirmationCodeRequestTypeVerifyEmail) { + body[kIDTokenKey] = _accessToken; + } + + // For email sign-in link requests, we only need an email address in addition to the already + // required fields. + if (_requestType == FIRGetOOBConfirmationCodeRequestTypeEmailLink) { + body[kEmailKey] = _email; + } + + // For email sign-in link requests, we only need an STS Access Token, a new email address in + // addition to the already required fields. + if (_requestType == FIRGetOOBConfirmationCodeRequestTypeVerifyBeforeUpdateEmail) { + body[kNewEmailKey] = _updatedEmail; + body[kIDTokenKey] = _accessToken; + } + + if (_continueURL) { + body[kContinueURLKey] = _continueURL; + } + + if (_iOSBundleID) { + body[kIosBundleIDKey] = _iOSBundleID; + } + + if (_androidPackageName) { + body[kAndroidPackageNameKey] = _androidPackageName; + } + + if (_androidMinimumVersion) { + body[kAndroidMinimumVersionKey] = _androidMinimumVersion; + } + + if (_androidInstallApp) { + body[kAndroidInstallAppKey] = @YES; + } + + if (_handleCodeInApp) { + body[kCanHandleCodeInAppKey] = @YES; + } + + if (_dynamicLinkDomain) { + body[kDynamicLinkDomainKey] = _dynamicLinkDomain; + } + + return body; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h new file mode 100644 index 00000000..9ea445e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGetOOBConfirmationCodeResponse + @brief Represents the response from the getOobConfirmationCode endpoint. + */ +@interface FIRGetOOBConfirmationCodeResponse : NSObject + +/** @property OOBCode + @brief The OOB code returned by the server in some cases. + */ +@property(nonatomic, copy, readonly, nullable) NSString *OOBCode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.m new file mode 100644 index 00000000..7eef6885 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kOOBCodeKey + @brief The name of the field in the response JSON for the OOB code. + */ +static NSString *const kOOBCodeKey = @"oobCode"; + +@implementation FIRGetOOBConfirmationCodeResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _OOBCode = [dictionary[kOOBCodeKey] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h new file mode 100644 index 00000000..cfaefccb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRGetProjectConfigRequest : FIRIdentityToolkitRequest + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithRequestConfiguration: + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithTemporaryProof:phoneNumberAPIKey + @brief Designated initializer. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.m new file mode 100644 index 00000000..402f2207 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.m @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kGetProjectConfigEndPoint + @brief The "getProjectConfig" endpoint. + */ +static NSString *const kGetProjectConfigEndPoint = @"getProjectConfig"; + +@implementation FIRGetProjectConfigRequest + +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + return [super initWithEndpoint:kGetProjectConfigEndPoint + requestConfiguration:requestConfiguration]; +} + +- (BOOL)containsPostBody { + return NO; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h new file mode 100644 index 00000000..12248e11 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRGetProjectConfigResponse + @brief Represents the response from the getProjectConfig endpoint. + */ +@interface FIRGetProjectConfigResponse : NSObject + +/** @property projectID + @brief The unique ID pertaining to the current project. + */ +@property(nonatomic, strong, readonly, nullable) NSString *projectID; + +/** @property authorizedDomains + @brief A list of domains whitelisted for the current project. + */ +@property(nonatomic, strong, readonly, nullable) NSArray *authorizedDomains; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.m new file mode 100644 index 00000000..38a3ba05 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.m @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRGetProjectConfigResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _projectID = [dictionary[@"projectId"] copy]; + id authorizedDomains = dictionary[@"authorizedDomains"]; + if ([authorizedDomains isKindOfClass:[NSString class]]) { + NSData *data = [authorizedDomains dataUsingEncoding:NSUTF8StringEncoding]; + authorizedDomains = [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableLeaves + error:nil]; + } + if ([authorizedDomains isKindOfClass:[NSArray class]]) { + _authorizedDomains = [[NSArray alloc] initWithArray:authorizedDomains copyItems:YES]; + } + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h new file mode 100644 index 00000000..1b918f50 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRResetPasswordRequest : FIRIdentityToolkitRequest + +/** @property oobCode + @brief The oobCode sent in the request. + */ +@property(nonatomic, copy, readonly) NSString *oobCode; + +/** @property updatedPassword + @brief The new password sent in the request. + */ +@property(nonatomic, copy, readonly) NSString *updatedPassword; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithOobCode:newPassword:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithOobCode:newPassword:requestConfiguration: + @brief Designated initializer. + @param oobCode The OOB Code. + @param newPassword The new password. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithOobCode:(NSString *)oobCode + newPassword:(nullable NSString *)newPassword + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.m new file mode 100644 index 00000000..9f70935e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.m @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kResetPasswordEndpoint + @brief The "resetPassword" endpoint. + */ +static NSString *const kResetPasswordEndpoint = @"resetPassword"; + +/** @var kOOBCodeKey + @brief The "resetPassword" key. + */ +static NSString *const kOOBCodeKey = @"oobCode"; + +/** @var kCurrentPasswordKey + @brief The "newPassword" key. + */ +static NSString *const kCurrentPasswordKey = @"newPassword"; + +@implementation FIRResetPasswordRequest + +- (nullable instancetype)initWithOobCode:(NSString *)oobCode + newPassword:(nullable NSString *)newPassword + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kResetPasswordEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _oobCode = oobCode; + _updatedPassword = newPassword; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + postBody[kOOBCodeKey] = _oobCode; + if (_updatedPassword) { + postBody[kCurrentPasswordKey] = _updatedPassword; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h new file mode 100644 index 00000000..3e8c5604 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthResetPasswordResponse + @brief Represents the response from the resetPassword endpoint. + @remarks Possible error codes: + - FIRAuthErrorCodeWeakPassword + - FIRAuthErrorCodeUserDisabled + - FIRAuthErrorCodeOperationNotAllowed + - FIRAuthErrorCodeExpiredActionCode + - FIRAuthErrorCodeInvalidActionCode + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/resetPassword + */ +@interface FIRResetPasswordResponse : NSObject + +/** @property email + @brief The email address corresponding to the reset password request. + */ +@property(nonatomic, strong, readonly) NSString *email; + +/** @property verifiedEmail + @brief The verified email returned from the backend. + */ +@property(nonatomic, strong, readonly) NSString *verifiedEmail; + +/** @property requestType + @brief The tpye of request as returned by the backend. + */ +@property(nonatomic, strong, readonly) NSString *requestType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.m new file mode 100644 index 00000000..5ad1e361 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.m @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRResetPasswordResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _email = [dictionary[@"email"] copy]; + _requestType = [dictionary[@"requestType"] copy]; + _verifiedEmail = [dictionary[@"newEmail"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h new file mode 100644 index 00000000..c17a2378 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @enum FIRSecureTokenRequestGrantType + @brief Represents the possible grant types for a token request. + */ +typedef NS_ENUM(NSUInteger, FIRSecureTokenRequestGrantType) { + /** @var FIRSecureTokenRequestGrantTypeAuthorizationCode + @brief Indicates an authorization code request. + @remarks Exchanges a Gitkit "ID Token" for an STS Access Token and Refresh Token. + */ + FIRSecureTokenRequestGrantTypeAuthorizationCode, + + /** @var FIRSecureTokenRequestGrantTypeRefreshToken + @brief Indicates an refresh token request. + @remarks Uses an existing Refresh Token to create a new Access Token. + */ + FIRSecureTokenRequestGrantTypeRefreshToken, +}; + +/** @class FIRSecureTokenRequest + @brief Represents the parameters for the token endpoint. + */ +@interface FIRSecureTokenRequest : NSObject + +/** @property grantType + @brief The type of grant requested. + @see FIRSecureTokenRequestGrantType + */ +@property(nonatomic, assign, readonly) FIRSecureTokenRequestGrantType grantType; + +/** @property scope + @brief The scopes requested (a comma-delimited list of scope strings.) + */ +@property(nonatomic, copy, readonly, nullable) NSString *scope; + +/** @property refreshToken + @brief The client's refresh token. + */ +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +/** @property code + @brief The client's authorization code (legacy Gitkit "ID Token"). + */ +@property(nonatomic, copy, readonly, nullable) NSString *code; + +/** @property APIKey + @brief The client's API Key. + */ +@property(nonatomic, copy, readonly) NSString *APIKey; + +/** @fn authCodeRequestWithCode: + @brief Creates an authorization code request with the given code (legacy Gitkit "ID Token"). + @param code The authorization code (legacy Gitkit "ID Token"). + @param requestConfiguration An object containing configurations to be added to the request. + @return An authorization request. + */ ++ (FIRSecureTokenRequest *)authCodeRequestWithCode:(NSString *)code + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn refreshRequestWithCode: + @brief Creates a refresh request with the given refresh token. + @param refreshToken The refresh token. + @param requestConfiguration An object containing configurations to be added to the request. + @return A refresh request. + */ ++ (FIRSecureTokenRequest *)refreshRequestWithRefreshToken:(NSString *)refreshToken + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn init + @brief Please use initWithGrantType:scope:refreshToken:code: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithGrantType:scope:refreshToken:code:APIKey: + @brief Designated initializer. + @param grantType The type of request. + @param scope The scopes requested. + @param refreshToken The client's refresh token (for refresh requests.) + @param code The client's authorization code (Gitkit ID Token) (for authorization code requests.) + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithGrantType:(FIRSecureTokenRequestGrantType)grantType + scope:(nullable NSString *)scope + refreshToken:(nullable NSString *)refreshToken + code:(nullable NSString *)code + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.m new file mode 100644 index 00000000..a2bbc1eb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.m @@ -0,0 +1,163 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h" + +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kFIRSecureTokenServiceGetTokenURLFormat + @brief The format of the secure token service URLs. Requires string format substitution with + the client's API Key. + */ +static NSString *const kFIRSecureTokenServiceGetTokenURLFormat = @"https://%@/v1/token?key=%@"; + +/** @var kFIRSecureTokenServiceGrantTypeRefreshToken + @brief The string value of the @c FIRSecureTokenRequestGrantTypeRefreshToken request type. + */ +static NSString *const kFIRSecureTokenServiceGrantTypeRefreshToken = @"refresh_token"; + +/** @var kFIRSecureTokenServiceGrantTypeAuthorizationCode + @brief The string value of the @c FIRSecureTokenRequestGrantTypeAuthorizationCode request type. + */ +static NSString *const kFIRSecureTokenServiceGrantTypeAuthorizationCode = @"authorization_code"; + +/** @var kGrantTypeKey + @brief The key for the "grantType" parameter in the request. + */ +static NSString *const kGrantTypeKey = @"grantType"; + +/** @var kScopeKey + @brief The key for the "scope" parameter in the request. + */ +static NSString *const kScopeKey = @"scope"; + +/** @var kRefreshTokenKey + @brief The key for the "refreshToken" parameter in the request. + */ +static NSString *const kRefreshTokenKey = @"refreshToken"; + +/** @var kCodeKey + @brief The key for the "code" parameter in the request. + */ +static NSString *const kCodeKey = @"code"; + +/** @var gAPIHost + @brief Host for server API calls. + */ +static NSString *gAPIHost = @"securetoken.googleapis.com"; + +@implementation FIRSecureTokenRequest { + /** @var _requestConfiguration + @brief Contains configuration relevant to the request. + */ + FIRAuthRequestConfiguration *_requestConfiguration; +} + ++ (FIRSecureTokenRequest *)authCodeRequestWithCode:(NSString *)code + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + return [[self alloc] initWithGrantType:FIRSecureTokenRequestGrantTypeAuthorizationCode + scope:nil + refreshToken:nil + code:code + requestConfiguration:requestConfiguration]; +} + ++ (FIRSecureTokenRequest *)refreshRequestWithRefreshToken:(NSString *)refreshToken + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + return [[self alloc] initWithGrantType:FIRSecureTokenRequestGrantTypeRefreshToken + scope:nil + refreshToken:refreshToken + code:nil + requestConfiguration:requestConfiguration]; +} + +/** @fn grantTypeStringWithGrantType: + @brief Converts a @c FIRSecureTokenRequestGrantType to it's @c NSString equivilent. + */ ++ (NSString *)grantTypeStringWithGrantType:(FIRSecureTokenRequestGrantType)grantType { + switch (grantType) { + case FIRSecureTokenRequestGrantTypeAuthorizationCode: + return kFIRSecureTokenServiceGrantTypeAuthorizationCode; + case FIRSecureTokenRequestGrantTypeRefreshToken: + return kFIRSecureTokenServiceGrantTypeRefreshToken; + // No Default case so we will notice if new grant types are added to the enum. + } +} + +- (nullable instancetype)initWithGrantType:(FIRSecureTokenRequestGrantType)grantType + scope:(nullable NSString *)scope + refreshToken:(nullable NSString *)refreshToken + code:(nullable NSString *)code + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super init]; + if (self) { + _grantType = grantType; + _scope = [scope copy]; + _refreshToken = [refreshToken copy]; + _code = [code copy]; + _APIKey = [requestConfiguration.APIKey copy]; + _requestConfiguration = requestConfiguration; + } + return self; +} + +- (FIRAuthRequestConfiguration *)requestConfiguration { + return _requestConfiguration; +} + +- (NSURL *)requestURL { + NSString *URLString = + [NSString stringWithFormat:kFIRSecureTokenServiceGetTokenURLFormat, gAPIHost, _APIKey]; + NSURL *URL = [NSURL URLWithString:URLString]; + return URL; +} + +- (BOOL)containsPostBody { + return YES; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = + [@{kGrantTypeKey : [[self class] grantTypeStringWithGrantType:_grantType]} mutableCopy]; + if (_scope) { + postBody[kScopeKey] = _scope; + } + if (_refreshToken) { + postBody[kRefreshTokenKey] = _refreshToken; + } + if (_code) { + postBody[kCodeKey] = _code; + } + return [postBody copy]; +} + +#pragma mark - Internal API for development + ++ (NSString *)host { + return gAPIHost; +} + ++ (void)setHost:(NSString *)host { + gAPIHost = host; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h new file mode 100644 index 00000000..a45f9ad4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRSecureTokenResponse + @brief Represents the response from the token endpoint. + */ +@interface FIRSecureTokenResponse : NSObject + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token. (Possibly an updated one for refresh requests.) + */ +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +/** @property accessToken + @brief The new access token. + */ +@property(nonatomic, copy, readonly, nullable) NSString *accessToken; + +/** @property IDToken + @brief The new ID Token. + */ +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.m new file mode 100644 index 00000000..5d4c00ae --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.m @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h" + +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kExpiresInKey + @brief The key for the number of seconds till the access token expires. + */ +static NSString *const kExpiresInKey = @"expires_in"; + +/** @var kRefreshTokenKey + @brief The key for the refresh token. + */ +static NSString *const kRefreshTokenKey = @"refresh_token"; + +/** @var kAccessTokenKey + @brief The key for the access token. + */ +static NSString *const kAccessTokenKey = @"access_token"; + +/** @var kIDTokenKey + @brief The key for the "id_token" value in the response. + */ +static NSString *const kIDTokenKey = @"id_token"; + +@implementation FIRSecureTokenResponse + +- (nullable NSString *)expectedKind { + return nil; +} + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _refreshToken = dictionary[kRefreshTokenKey]; + _accessToken = dictionary[kAccessTokenKey]; + _IDToken = dictionary[kIDTokenKey]; + if (!_accessToken.length) { + if (error) { + *error = [FIRAuthErrorUtils unexpectedResponseWithDeserializedResponse:dictionary]; + } + return NO; + } + id expiresIn = dictionary[kExpiresInKey]; + if (![expiresIn isKindOfClass:[NSString class]]) { + if (error) { + *error = [FIRAuthErrorUtils unexpectedResponseWithDeserializedResponse:dictionary]; + } + return NO; + } + + _approximateExpirationDate = [NSDate dateWithTimeIntervalSinceNow:[expiresIn doubleValue]]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h new file mode 100644 index 00000000..974eb6a4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +@class FIRAuthAppCredential; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRSendVerificationCodeRequest : FIRIdentityToolkitRequest + +/** @property phoneNumber + @brief The phone number to which the verification code should be sent. + */ +@property(nonatomic, strong, readonly) NSString *phoneNumber; + +/** @property appCredential + @brief The credential to prove the identity of the app in order to send the verification code. + */ +@property(nonatomic, strong, readonly, nullable) FIRAuthAppCredential *appCredential; + +/** @property reCAPTCHAToken + @brief The reCAPTCHA token to prove the identity of the app in order to send the verification + code. + */ +@property(nonatomic, strong, readonly, nullable) NSString *reCAPTCHAToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithPhoneNumber:appCredentials:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithPhoneNumber:appCredentials:requestConfiguration: + @brief Designated initializer. + @param phoneNumber The phone number to which the verification code is to be sent. + @param appCredential The credential that proves the identity of the app. + @param reCAPTCHAToken The reCAPTCHA token that proves the identity of the app. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber + appCredential:(nullable FIRAuthAppCredential *)appCredential + reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.m new file mode 100644 index 00000000..b0eb544d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.m @@ -0,0 +1,84 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h" + +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kSendVerificationCodeEndPoint + @brief The "sendVerificationCodeEnd" endpoint. + */ +static NSString *const kSendVerificationCodeEndPoint = @"sendVerificationCode"; + +/** @var kPhoneNumberKey + @brief The key for the Phone Number parameter in the request. + */ +static NSString *const kPhoneNumberKey = @"phoneNumber"; + +/** @var kReceiptKey + @brief The key for the receipt parameter in the request. + */ +static NSString *const kReceiptKey = @"iosReceipt"; + +/** @var kSecretKey + @brief The key for the Secret parameter in the request. + */ +static NSString *const kSecretKey = @"iosSecret"; + +/** @var kreCAPTCHATokenKey + @brief The key for the reCAPTCHAToken parameter in the request. + */ +static NSString *const kreCAPTCHATokenKey = @"recaptchaToken"; + +@implementation FIRSendVerificationCodeRequest { +} + +- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber + appCredential:(nullable FIRAuthAppCredential *)appCredential + reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kSendVerificationCodeEndPoint + requestConfiguration:requestConfiguration]; + if (self) { + _phoneNumber = [phoneNumber copy]; + _appCredential = appCredential; + _reCAPTCHAToken = [reCAPTCHAToken copy]; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_phoneNumber) { + postBody[kPhoneNumberKey] = _phoneNumber; + } + if (_appCredential.receipt) { + postBody[kReceiptKey] = _appCredential.receipt; + } + if (_appCredential.secret) { + postBody[kSecretKey] = _appCredential.secret; + } + if (_reCAPTCHAToken) { + postBody[kreCAPTCHATokenKey] = _reCAPTCHAToken; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h new file mode 100644 index 00000000..605f3f47 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRSendVerificationCodeResponse : NSObject + +/** @property verificationID + @brief Encrypted session information returned by the backend. + */ +@property(nonatomic, readonly) NSString *verificationID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.m new file mode 100644 index 00000000..6e8598cb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRSendVerificationCodeResponse + +// TODO: remove when resolving b/37169084 . +- (nullable NSString *)expectedKind { + return nil; +} + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _verificationID = [dictionary[@"sessionInfo"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h new file mode 100644 index 00000000..5ba22bae --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +@class FIRGetAccountInfoResponse; + +NS_ASSUME_NONNULL_BEGIN + +/** @var FIRSetAccountInfoUserAttributeEmail + @brief Constant for email attribute used in "deleteAttributes". + */ +extern NSString *const FIRSetAccountInfoUserAttributeEmail; + +/** @var FIRSetAccountInfoUserAttributeDisplayName + @brief Constant for displayName attribute used in "deleteAttributes". + */ +extern NSString *const FIRSetAccountInfoUserAttributeDisplayName; + +/** @var FIRSetAccountInfoUserAttributeProvider + @brief Constant for provider attribute used in "deleteAttributes". + */ +extern NSString *const FIRSetAccountInfoUserAttributeProvider; + +/** @var FIRSetAccountInfoUserAttributePhotoURL + @brief Constant for photoURL attribute used in "deleteAttributes". + */ +extern NSString *const FIRSetAccountInfoUserAttributePhotoURL; + +/** @var FIRSetAccountInfoUserAttributePassword + @brief Constant for password attribute used in "deleteAttributes". + */ +extern NSString *const FIRSetAccountInfoUserAttributePassword; + +/** @class FIRSetAccountInfoRequest + @brief Represents the parameters for the setAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/setAccountInfo + */ +@interface FIRSetAccountInfoRequest : FIRIdentityToolkitRequest + +/** @property accessToken + @brief The STS Access Token of the authenticated user. + */ +@property(nonatomic, copy, nullable) NSString *accessToken; + +/** @property displayName + @brief The name of the user. + */ +@property(nonatomic, copy, nullable) NSString *displayName; + +/** @property localID + @brief The local ID of the user. + */ +@property(nonatomic, copy, nullable) NSString *localID; + +/** @property email + @brief The email of the user. + */ +@property(nonatomic, copy, nullable) NSString *email; + +/** @property photoURL + @brief The photoURL of the user. + */ +@property(nonatomic, copy, nullable) NSURL *photoURL; + +/** @property password + @brief The new password of the user. + */ +@property(nonatomic, copy, nullable) NSString *password; + +/** @property providers + @brief The associated identity providers of the user. + */ +@property(nonatomic, copy, nullable) NSArray *providers; + +/** @property OOBCode + @brief The out-of-band code of the change email request. + */ +@property(nonatomic, copy, nullable) NSString *OOBCode; + +/** @property emailVerified + @brief Whether to mark the email as verified or not. + */ +@property(nonatomic, assign) BOOL emailVerified; + +/** @property upgradeToFederatedLogin + @brief Whether to mark the user to upgrade to federated login. + */ +@property(nonatomic, assign) BOOL upgradeToFederatedLogin; + +/** @property captchaChallenge + @brief The captcha challenge. + */ +@property(nonatomic, copy, nullable) NSString *captchaChallenge; + +/** @property captchaResponse + @brief Response to the captcha. + */ +@property(nonatomic, copy, nullable) NSString *captchaResponse; + +/** @property deleteAttributes + @brief The list of user attributes to delete. + @remarks Every element of the list must be one of the predefined constant starts with + "FIRSetAccountInfoUserAttribute". + */ +@property(nonatomic, copy, nullable) NSArray *deleteAttributes; + +/** @property deleteProviders + @brief The list of identity providers to delete. + */ +@property(nonatomic, copy, nullable) NSArray *deleteProviders; + +/** @property returnSecureToken + @brief Whether the response should return access token and refresh token directly. + @remarks The default value is @c YES . + */ +@property(nonatomic, assign) BOOL returnSecureToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithAPIKey:email:password:displayName:requestConfiguration instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithRequestConfiguration: + @brief Designated initializer. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.m new file mode 100644 index 00000000..99415868 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.m @@ -0,0 +1,179 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +NSString *const FIRSetAccountInfoUserAttributeEmail = @"EMAIL"; + +NSString *const FIRSetAccountInfoUserAttributeDisplayName = @"DISPLAY_NAME"; + +NSString *const FIRSetAccountInfoUserAttributeProvider = @"PROVIDER"; + +NSString *const FIRSetAccountInfoUserAttributePhotoURL = @"PHOTO_URL"; + +NSString *const FIRSetAccountInfoUserAttributePassword = @"PASSWORD"; + +/** @var kCreateAuthURIEndpoint + @brief The "setAccountInfo" endpoint. + */ +static NSString *const kSetAccountInfoEndpoint = @"setAccountInfo"; + +/** @var kIDTokenKey + @brief The key for the "idToken" value in the request. This is actually the STS Access Token, + despite it's confusing (backwards compatiable) parameter name. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kDisplayNameKey + @brief The key for the "displayName" value in the request. + */ +static NSString *const kDisplayNameKey = @"displayName"; + +/** @var kLocalIDKey + @brief The key for the "localID" value in the request. + */ +static NSString *const kLocalIDKey = @"localId"; + +/** @var kEmailKey + @brief The key for the "email" value in the request. + */ +static NSString *const kEmailKey = @"email"; + +/** @var kPasswordKey + @brief The key for the "password" value in the request. + */ +static NSString *const kPasswordKey = @"password"; + +/** @var kPhotoURLKey + @brief The key for the "photoURL" value in the request. + */ +static NSString *const kPhotoURLKey = @"photoUrl"; + +/** @var kProvidersKey + @brief The key for the "providers" value in the request. + */ +static NSString *const kProvidersKey = @"provider"; + +/** @var kOOBCodeKey + @brief The key for the "OOBCode" value in the request. + */ +static NSString *const kOOBCodeKey = @"oobCode"; + +/** @var kEmailVerifiedKey + @brief The key for the "emailVerified" value in the request. + */ +static NSString *const kEmailVerifiedKey = @"emailVerified"; + +/** @var kUpgradeToFederatedLoginKey + @brief The key for the "upgradeToFederatedLogin" value in the request. + */ +static NSString *const kUpgradeToFederatedLoginKey = @"upgradeToFederatedLogin"; + +/** @var kCaptchaChallengeKey + @brief The key for the "captchaChallenge" value in the request. + */ +static NSString *const kCaptchaChallengeKey = @"captchaChallenge"; + +/** @var kCaptchaResponseKey + @brief The key for the "captchaResponse" value in the request. + */ +static NSString *const kCaptchaResponseKey = @"captchaResponse"; + +/** @var kDeleteAttributesKey + @brief The key for the "deleteAttribute" value in the request. + */ +static NSString *const kDeleteAttributesKey = @"deleteAttribute"; + +/** @var kDeleteProvidersKey + @brief The key for the "deleteProvider" value in the request. + */ +static NSString *const kDeleteProvidersKey = @"deleteProvider"; + +/** @var kReturnSecureTokenKey + @brief The key for the "returnSecureToken" value in the request. + */ +static NSString *const kReturnSecureTokenKey = @"returnSecureToken"; + +@implementation FIRSetAccountInfoRequest + +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kSetAccountInfoEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _returnSecureToken = YES; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_accessToken) { + postBody[kIDTokenKey] = _accessToken; + } + if (_displayName) { + postBody[kDisplayNameKey] = _displayName; + } + if (_localID) { + postBody[kLocalIDKey] = _localID; + } + if (_email) { + postBody[kEmailKey] = _email; + } + if (_password) { + postBody[kPasswordKey] = _password; + } + if (_photoURL) { + postBody[kPhotoURLKey] = _photoURL.absoluteString; + } + if (_providers) { + postBody[kProvidersKey] = _providers; + } + if (_OOBCode) { + postBody[kOOBCodeKey] = _OOBCode; + } + if (_emailVerified) { + postBody[kEmailVerifiedKey] = @YES; + } + if (_upgradeToFederatedLogin) { + postBody[kUpgradeToFederatedLoginKey] = @YES; + } + if (_captchaChallenge) { + postBody[kCaptchaChallengeKey] = _captchaChallenge; + } + if (_captchaResponse) { + postBody[kCaptchaResponseKey] = _captchaResponse; + } + if (_deleteAttributes) { + postBody[kDeleteAttributesKey] = _deleteAttributes; + } + if (_deleteProviders) { + postBody[kDeleteProvidersKey] = _deleteProviders; + } + if (_returnSecureToken) { + postBody[kReturnSecureTokenKey] = @YES; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h new file mode 100644 index 00000000..9e309304 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h @@ -0,0 +1,98 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRSetAccountInfoResponseProviderUserInfo + @brief Represents the provider user info part of the response from the setAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/setAccountInfo + */ +@interface FIRSetAccountInfoResponseProviderUserInfo : NSObject + +/** @property providerID + @brief The ID of the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *providerID; + +/** @property displayName + @brief The user's display name at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property photoURL + @brief The user's photo URL at the identity provider. + */ +@property(nonatomic, strong, readonly, nullable) NSURL *photoURL; + +/** @fn init + @brief Please use initWithDictionary: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithAPIKey: + @brief Designated initializer. + @param dictionary The provider user info data from endpoint. + */ +- (instancetype)initWithDictionary:(NSDictionary *)dictionary NS_DESIGNATED_INITIALIZER; + +@end + +/** @class FIRSetAccountInfoResponse + @brief Represents the response from the setAccountInfo endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/setAccountInfo + */ +@interface FIRSetAccountInfoResponse : NSObject + +/** @property email + @brief The email or the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property displayName + @brief The display name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property providerUserInfo + @brief The user's profiles at the associated identity providers. + */ +@property(nonatomic, strong, readonly, nullable) + NSArray *providerUserInfo; + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.m new file mode 100644 index 00000000..138fba3e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.m @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRSetAccountInfoResponseProviderUserInfo + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _providerID = [dictionary[@"providerId"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + NSString *photoURL = dictionary[@"photoUrl"]; + if (photoURL) { + _photoURL = [NSURL URLWithString:photoURL]; + } + } + return self; +} + +@end + +@implementation FIRSetAccountInfoResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _email = [dictionary[@"email"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + _IDToken = [dictionary[@"idToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + _refreshToken = [dictionary[@"refreshToken"] copy]; + NSArray *providerUserInfoData = dictionary[@"providerUserInfo"]; + if (providerUserInfoData) { + NSMutableArray *providerUserInfoArray = + [NSMutableArray arrayWithCapacity:providerUserInfoData.count]; + for (NSDictionary *dictionary in providerUserInfoData) { + [providerUserInfoArray addObject:[[FIRSetAccountInfoResponseProviderUserInfo alloc] + initWithDictionary:dictionary]]; + } + _providerUserInfo = [providerUserInfoArray copy]; + } + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h new file mode 100644 index 00000000..781d63a2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRSignInWithGameCenterRequest + @brief The request to sign in with Game Center account + */ +@interface FIRSignInWithGameCenterRequest : FIRIdentityToolkitRequest + +/** @property playerID + @brief The playerID to verify. + */ +@property(nonatomic, copy) NSString *playerID; + +/** @property publicKeyURL + @brief The URL for the public encryption key. + */ +@property(nonatomic, copy) NSURL *publicKeyURL; + +/** @property signature + @brief The verification signature data generated by Game Center. + */ +@property(nonatomic, copy) NSData *signature; + +/** @property salt + @brief A random strong used to compute the hash and keep it randomized. + */ +@property(nonatomic, copy) NSData *salt; + +/** @property timestamp + @brief The date and time that the signature was created. + */ +@property(nonatomic, assign) uint64_t timestamp; + +/** @property accessToken + @brief The STS Access Token for the authenticated user, only needed for linking the user. + */ +@property(nonatomic, copy, nullable) NSString *accessToken; + +/** @property displayName + @brief The display name of the local Game Center player. + */ +@property(nonatomic, copy, nullable) NSString *displayName; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithPlayerID:publicKeyURL:signature:salt:timestamp:requestConfiguration:. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithPlayerID:publicKeyURL:signature:salt:timestamp:displayName:requestConfiguration: + @brief Designated initializer. + @param playerID The ID of the Game Center player. + @param publicKeyURL The URL for the public encryption key. + @param signature The verification signature generated. + @param salt A random string used to compute the hash and keep it randomized. + @param timestamp The date and time that the signature was created. + @param displayName The display name of the Game Center player. + */ +- (nullable instancetype)initWithPlayerID:(NSString *)playerID + publicKeyURL:(NSURL *)publicKeyURL + signature:(NSData *)signature + salt:(NSData *)salt + timestamp:(uint64_t)timestamp + displayName:(NSString *)displayName + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.m new file mode 100644 index 00000000..864b9696 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.m @@ -0,0 +1,80 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h" + +#import "FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kSignInWithGameCenterEndPoint + @brief The "SignInWithGameCenter" endpoint. + */ +static NSString *const kSignInWithGameCenterEndPoint = @"signInWithGameCenter"; + +@implementation FIRSignInWithGameCenterRequest + +- (nullable instancetype)initWithPlayerID:(NSString *)playerID + publicKeyURL:(NSURL *)publicKeyURL + signature:(NSData *)signature + salt:(NSData *)salt + timestamp:(uint64_t)timestamp + displayName:(NSString *)displayName + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kSignInWithGameCenterEndPoint + requestConfiguration:requestConfiguration]; + if (self) { + _playerID = playerID; + _publicKeyURL = [publicKeyURL copy]; + _signature = [signature copy]; + _salt = [salt copy]; + _timestamp = timestamp; + _displayName = displayName; + } + return self; +} + +#pragma mark - FIRAuthRPCRequest + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_playerID) { + postBody[@"playerId"] = _playerID; + } + if (_publicKeyURL) { + postBody[@"publicKeyUrl"] = _publicKeyURL.absoluteString; + } + if (_signature) { + postBody[@"signature"] = [_signature fir_base64URLEncodedStringWithOptions:0]; + } + if (_salt) { + postBody[@"salt"] = [_salt fir_base64URLEncodedStringWithOptions:0]; + } + if (_timestamp != 0) { + postBody[@"timestamp"] = [NSNumber numberWithUnsignedLongLong:_timestamp]; + } + if (_accessToken) { + postBody[@"idToken"] = _accessToken; + } + if (_displayName) { + postBody[@"displayName"] = _displayName; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h new file mode 100644 index 00000000..ee07b3e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h @@ -0,0 +1,64 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRSignInWithGameCenterResponse : NSObject + +/** @property IDToken + @breif Either an authorization code suitable for performing an STS token exchange, or the access + token from Secure Token Service, depending on whether @c returnSecureToken is set on the + request. + */ +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +/** @property refreshToken + @breif @breif The refresh token from Secure Token Service. + */ +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +/** @property localID + @breif @breif The Firebase Auth user ID. + */ +@property(nonatomic, copy, readonly, nullable) NSString *localID; + +/** @property playerID + @breif @breif The verified player ID. + */ +@property(nonatomic, copy, readonly, nullable) NSString *playerID; + +/** @property approximateExpirationDate + @breif The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property isNewUser + @breif Flag indicating that the user signing in is a new user and not a returning user. + */ +@property(nonatomic, assign) BOOL isNewUser; + +/** @property displayName + @breif The user's Game Center display name. + */ +@property(nonatomic, copy, readonly, nullable) NSString *displayName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.m new file mode 100644 index 00000000..ebad3158 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.m @@ -0,0 +1,40 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRSignInWithGameCenterResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _localID = [dictionary[@"localId"] copy]; + _approximateExpirationDate = nil; + if ([dictionary[@"expiresIn"] isKindOfClass:[NSString class]]) { + _approximateExpirationDate = + [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] integerValue]]; + } + _playerID = [dictionary[@"playerId"] copy]; + _isNewUser = [dictionary[@"isNewUser"] boolValue]; + _displayName = [dictionary[@"displayName"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h new file mode 100644 index 00000000..070290d0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRSignUpNewUserRequest : FIRIdentityToolkitRequest + +/** @property email + @brief The email of the user. + */ +@property(nonatomic, copy, nullable) NSString *email; + +/** @property password + @brief The password inputed by the user. + */ +@property(nonatomic, copy, nullable) NSString *password; + +/** @property displayName + @brief The password inputed by the user. + */ +@property(nonatomic, copy, nullable) NSString *displayName; + +/** @property returnSecureToken + @brief Whether the response should return access token and refresh token directly. + @remarks The default value is @c YES . + */ +@property(nonatomic, assign) BOOL returnSecureToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithAPIKey:email:password:displayName:requestConfiguration instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithEndpoint:requestConfiguration: + @brief initializer for anonymous sign-in. + */ +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration; + +/** @fn initWithAPIKey:email:password:displayName:requestConfiguration + @brief Designated initializer. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithEmail:(nullable NSString *)email + password:(nullable NSString *)password + displayName:(nullable NSString *)displayName + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.m new file mode 100644 index 00000000..548ca932 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.m @@ -0,0 +1,90 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kSignupNewUserEndpoint + @brief The "SingupNewUserEndpoint" endpoint. + */ +static NSString *const kSignupNewUserEndpoint = @"signupNewUser"; + +/** @var kEmailKey + @brief The key for the "email" value in the request. + */ +static NSString *const kEmailKey = @"email"; + +/** @var kPasswordKey + @brief The key for the "password" value in the request. + */ +static NSString *const kPasswordKey = @"password"; + +/** @var kDisplayNameKey + @brief The key for the "kDisplayName" value in the request. + */ +static NSString *const kDisplayNameKey = @"displayName"; + +/** @var kReturnSecureTokenKey + @brief The key for the "returnSecureToken" value in the request. + */ +static NSString *const kReturnSecureTokenKey = @"returnSecureToken"; + +@implementation FIRSignUpNewUserRequest + +- (nullable instancetype)initWithEmail:(nullable NSString *)email + password:(nullable NSString *)password + displayName:(nullable NSString *)displayName + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kSignupNewUserEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _email = [email copy]; + _password = [password copy]; + _displayName = [displayName copy]; + _returnSecureToken = YES; + } + return self; +} + +- (nullable instancetype)initWithRequestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + self = [self initWithEmail:nil + password:nil + displayName:nil + requestConfiguration:requestConfiguration]; + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_email) { + postBody[kEmailKey] = _email; + } + if (_password) { + postBody[kPasswordKey] = _password; + } + if (_displayName) { + postBody[kDisplayNameKey] = _displayName; + } + if (_returnSecureToken) { + postBody[kReturnSecureTokenKey] = @YES; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h new file mode 100644 index 00000000..f2e74f6a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRSignUpNewUserResponse : NSObject + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.m new file mode 100644 index 00000000..bdfa6d56 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRSignUpNewUserResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + _refreshToken = [dictionary[@"refreshToken"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h new file mode 100644 index 00000000..0a1aa370 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h @@ -0,0 +1,118 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyAssertionRequest + @brief Represents the parameters for the verifyAssertion endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyAssertion + */ +@interface FIRVerifyAssertionRequest : FIRIdentityToolkitRequest + +/** @property requestURI + @brief The URI to which the IDP redirects the user back. It may contain federated login result + params added by the IDP. + */ +@property(nonatomic, copy, nullable) NSString *requestURI; + +/** @property pendingToken + @brief The Firebase ID Token for the IDP pending to be confirmed by the user. + */ +@property(nonatomic, copy, nullable) NSString *pendingToken; + +/** @property accessToken + @brief The STS Access Token for the authenticated user, only needed for linking the user. + */ +@property(nonatomic, copy, nullable) NSString *accessToken; + +/** @property returnSecureToken + @brief Whether the response should return access token and refresh token directly. + @remarks The default value is @c YES . + */ +@property(nonatomic, assign) BOOL returnSecureToken; + +#pragma mark - Components of "postBody" + +/** @property providerID + @brief The ID of the IDP whose credentials are being presented to the endpoint. + */ +@property(nonatomic, copy, readonly) NSString *providerID; + +/** @property providerAccessToken + @brief An access token from the IDP. + */ +@property(nonatomic, copy, nullable) NSString *providerAccessToken; + +/** @property providerIDToken + @brief An ID Token from the IDP. + */ +@property(nonatomic, copy, nullable) NSString *providerIDToken; + +/** @property providerRawNonce + @brief An raw nonce from the IDP. + */ +@property(nonatomic, copy, nullable) NSString *providerRawNonce; + +/** @property returnIDPCredential + @brief Whether the response should return the IDP credential directly. + */ +@property(nonatomic, assign) BOOL returnIDPCredential; + +/** @property providerOAuthTokenSecret + @brief A session ID used to map this request to a headful-lite flow. + */ +@property(nonatomic, copy, nullable) NSString *sessionID; + +/** @property providerOAuthTokenSecret + @brief An OAuth client secret from the IDP. + */ +@property(nonatomic, copy, nullable) NSString *providerOAuthTokenSecret; + +/** @property inputEmail + @brief The originally entered email in the UI. + */ +@property(nonatomic, copy, nullable) NSString *inputEmail; + +/** @property autoCreate + @brief A flag that indicates whether or not the user should be automatically created. + */ +@property(nonatomic, assign) BOOL autoCreate; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithProviderID:requestConfifuration instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithProviderID:requestConfifuration + @brief Designated initializer. + @param providerID The auth provider's ID. + @param requestConfiguration An object containing configurations to be added to the request. + + */ +- (nullable instancetype)initWithProviderID:(NSString *)providerID + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.m new file mode 100644 index 00000000..2b530518 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.m @@ -0,0 +1,177 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kVerifyAssertionEndpoint + @brief The "verifyAssertion" endpoint. + */ +static NSString *const kVerifyAssertionEndpoint = @"verifyAssertion"; + +/** @var kProviderIDKey + @brief The key for the "providerId" value in the request. + */ +static NSString *const kProviderIDKey = @"providerId"; + +/** @var kProviderIDTokenKey + @brief The key for the "id_token" value in the request. + */ +static NSString *const kProviderIDTokenKey = @"id_token"; + +/** @var kProviderNonceKey + @brief The key for the "nonce" value in the request. + */ +static NSString *const kProviderNonceKey = @"nonce"; + +/** @var kProviderAccessTokenKey + @brief The key for the "access_token" value in the request. + */ +static NSString *const kProviderAccessTokenKey = @"access_token"; + +/** @var kProviderOAuthTokenSecretKey + @brief The key for the "oauth_token_secret" value in the request. + */ +static NSString *const kProviderOAuthTokenSecretKey = @"oauth_token_secret"; + +/** @var kIdentifierKey + @brief The key for the "identifier" value in the request. + */ +static NSString *const kIdentifierKey = @"identifier"; + +/** @var kRequestURIKey + @brief The key for the "requestUri" value in the request. + */ +static NSString *const kRequestURIKey = @"requestUri"; + +/** @var kPostBodyKey + @brief The key for the "postBody" value in the request. + */ +static NSString *const kPostBodyKey = @"postBody"; + +/** @var kPendingTokenKey + @brief The key for the "pendingToken" value in the request. + */ +static NSString *const kPendingTokenKey = @"pendingToken"; + +/** @var kAutoCreateKey + @brief The key for the "autoCreate" value in the request. + */ +static NSString *const kAutoCreateKey = @"autoCreate"; + +/** @var kIDTokenKey + @brief The key for the "idToken" value in the request. This is actually the STS Access Token, + despite it's confusing (backwards compatiable) parameter name. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kReturnSecureTokenKey + @brief The key for the "returnSecureToken" value in the request. + */ +static NSString *const kReturnSecureTokenKey = @"returnSecureToken"; + +/** @var kReturnIDPCredentialKey + @brief The key for the "returnIdpCredential" value in the request. + */ +static NSString *const kReturnIDPCredentialKey = @"returnIdpCredential"; + +/** @var kSessionIDKey + @brief The key for the "sessionID" value in the request. + */ +static NSString *const kSessionIDKey = @"sessionId"; + +@implementation FIRVerifyAssertionRequest + +- (nullable instancetype)initWithProviderID:(NSString *)providerID + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyAssertionEndpoint + requestConfiguration:requestConfiguration]; + if (self) { + _providerID = providerID; + _returnSecureToken = YES; + _autoCreate = YES; + _returnIDPCredential = YES; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSURLComponents *components = [[NSURLComponents alloc] init]; + NSMutableArray *queryItems = + [@[ [NSURLQueryItem queryItemWithName:kProviderIDKey value:_providerID] ] mutableCopy]; + + if (_providerIDToken) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderIDTokenKey + value:_providerIDToken]]; + } + + if (_providerRawNonce) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderNonceKey + value:_providerRawNonce]]; + } + + if (_providerAccessToken) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderAccessTokenKey + value:_providerAccessToken]]; + } + + if (!_providerIDToken && !_providerAccessToken && !_pendingToken && !_requestURI) { + [NSException + raise:NSInvalidArgumentException + format:@"One of IDToken, accessToken, pendingToken, or requestURI must be supplied."]; + } + + if (_providerOAuthTokenSecret) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderOAuthTokenSecretKey + value:_providerOAuthTokenSecret]]; + } + + if (_inputEmail) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:kIdentifierKey value:_inputEmail]]; + } + [components setQueryItems:queryItems]; + NSMutableDictionary *body = [@{ + kRequestURIKey : _requestURI ?: @"http://localhost", // Unused by server, but required + kPostBodyKey : [components query] + } mutableCopy]; + + if (_pendingToken) { + body[kPendingTokenKey] = _pendingToken; + } + if (_accessToken) { + body[kIDTokenKey] = _accessToken; + } + if (_returnSecureToken) { + body[kReturnSecureTokenKey] = @YES; + } + + if (_returnIDPCredential) { + body[kReturnIDPCredentialKey] = @YES; + } + + if (_sessionID) { + body[kSessionIDKey] = _sessionID; + } + + body[kAutoCreateKey] = @(_autoCreate); + + return body; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h new file mode 100644 index 00000000..d739467b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h @@ -0,0 +1,214 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyAssertionResponse + @brief Represents the response from the verifyAssertion endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyAssertion + */ +@interface FIRVerifyAssertionResponse : NSObject + +/** @property federatedID + @brief The unique ID identifies the IdP account. + */ +@property(nonatomic, strong, readonly, nullable) NSString *federatedID; + +/** @property providerID + @brief The IdP ID. For white listed IdPs it's a short domain name e.g. google.com, aol.com, + live.net and yahoo.com. If the "providerId" param is set to OpenID OP identifer other than + the whilte listed IdPs the OP identifier is returned. If the "identifier" param is federated + ID in the createAuthUri request. The domain part of the federated ID is returned. + */ +@property(nonatomic, strong, readonly, nullable) NSString *providerID; + +/** @property localID + @brief The RP local ID if it's already been mapped to the IdP account identified by the + federated ID. + */ +@property(nonatomic, strong, readonly, nullable) NSString *localID; + +/** @property email + @brief The email returned by the IdP. NOTE: The federated login user may not own the email. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property inputEmail + @brief It's the identifier param in the createAuthUri request if the identifier is an email. It + can be used to check whether the user input email is different from the asserted email. + */ +@property(nonatomic, strong, readonly, nullable) NSString *inputEmail; + +/** @property originalEmail + @brief The original email stored in the mapping storage. It's returned when the federated ID is + associated to a different email. + */ +@property(nonatomic, strong, readonly, nullable) NSString *originalEmail; + +/** @property oauthRequestToken + @brief The user approved request token for the OpenID OAuth extension. + */ +@property(nonatomic, strong, readonly, nullable) NSString *oauthRequestToken; + +/** @property oauthScope + @brief The scope for the OpenID OAuth extension. + */ +@property(nonatomic, strong, readonly, nullable) NSString *oauthScope; + +/** @property firstName + @brief The first name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *firstName; + +/** @property lastName + @brief The last name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *lastName; + +/** @property fullName + @brief The full name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *fullName; + +/** @property nickName + @brief The nick name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *nickName; + +/** @property displayName + @brief The display name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +/** @property action + @brief The action code. + */ +@property(nonatomic, strong, readonly, nullable) NSString *action; + +/** @property language + @brief The language preference of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *language; + +/** @property timeZone + @brief The timezone of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *timeZone; + +/** @property photoURL + @brief The URI of the public accessible profile picture. + */ +@property(nonatomic, strong, readonly, nullable) NSURL *photoURL; + +/** @property dateOfBirth + @brief The birth date of the IdP account. + */ +@property(nonatomic, strong, readonly, nullable) NSString *dateOfBirth; + +/** @property context + @brief The opaque value used by the client to maintain context info between the authentication + request and the IDP callback. + */ +@property(nonatomic, strong, readonly, nullable) NSString *context; + +/** @property verifiedProvider + @brief When action is 'map', contains the idps which can be used for confirmation. + */ +@property(nonatomic, strong, readonly, nullable) NSArray *verifiedProvider; + +/** @property needConfirmation + @brief Whether the assertion is from a non-trusted IDP and need account linking confirmation. + */ +@property(nonatomic, assign) BOOL needConfirmation; + +/** @property emailRecycled + @brief It's true if the email is recycled. + */ +@property(nonatomic, assign) BOOL emailRecycled; + +/** @property emailVerified + @brief The value is true if the IDP is also the email provider. It means the user owns the + email. + */ +@property(nonatomic, assign) BOOL emailVerified; + +/** @property isNewUser + @brief Flag indicating that the user signing in is a new user and not a returning user. + */ +@property(nonatomic, assign) BOOL isNewUser; + +/** @property profile + @brief Dictionary containing the additional IdP specific information. + */ +@property(nonatomic, readonly, nullable) NSDictionary *profile; + +/** @property username + @brief The name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *username; + +/** @property oauthIDToken + @brief The ID token for the OpenID OAuth extension. + */ +@property(nonatomic, strong, readonly, nullable) NSString *oauthIDToken; + +/** @property oauthExpirationDate + @brief The approximate expiration date of the oauth access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *oauthExpirationDate; + +/** @property oauthAccessToken + @brief The access token for the OpenID OAuth extension. + */ +@property(nonatomic, strong, readonly, nullable) NSString *oauthAccessToken; + +/** @property oauthSecretToken + @brief The secret for the OpenID OAuth extention. + */ +@property(nonatomic, readonly, nullable) NSString *oauthSecretToken; + +/** @property pendingToken + @brief The pending ID Token string. + */ +@property(nonatomic, copy, nullable) NSString *pendingToken; + +@property(nonatomic, strong, readonly, nullable) NSString *MFAPendingCredential; + +@property(nonatomic, strong, readonly, nullable) NSArray *MFAInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.m new file mode 100644 index 00000000..6c605e74 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.m @@ -0,0 +1,100 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRVerifyAssertionResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _federatedID = [dictionary[@"federatedId"] copy]; + _providerID = [dictionary[@"providerId"] copy]; + _localID = [dictionary[@"localId"] copy]; + _emailRecycled = [dictionary[@"emailRecycled"] boolValue]; + _emailVerified = [dictionary[@"emailVerified"] boolValue]; + _email = [dictionary[@"email"] copy]; + _inputEmail = [dictionary[@"inputEmail"] copy]; + _originalEmail = [dictionary[@"originalEmail"] copy]; + _oauthRequestToken = [dictionary[@"oauthRequestToken"] copy]; + _oauthScope = [dictionary[@"oauthScope"] copy]; + _firstName = [dictionary[@"firstName"] copy]; + _lastName = [dictionary[@"lastName"] copy]; + _fullName = [dictionary[@"fullName"] copy]; + _nickName = [dictionary[@"nickName"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + _IDToken = [dictionary[@"idToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _isNewUser = [dictionary[@"isNewUser"] boolValue]; + id rawUserInfo = dictionary[@"rawUserInfo"]; + if ([rawUserInfo isKindOfClass:[NSString class]]) { + NSData *data = [rawUserInfo dataUsingEncoding:NSUTF8StringEncoding]; + rawUserInfo = [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableLeaves + error:nil]; + } + if ([rawUserInfo isKindOfClass:[NSDictionary class]]) { + _profile = [[NSDictionary alloc] initWithDictionary:rawUserInfo copyItems:YES]; + } + _username = [dictionary[@"username"] copy]; + _action = [dictionary[@"action"] copy]; + _language = [dictionary[@"language"] copy]; + _timeZone = [dictionary[@"timeZone"] copy]; + _photoURL = dictionary[@"photoUrl"] ? [NSURL URLWithString:dictionary[@"photoUrl"]] : nil; + _dateOfBirth = [dictionary[@"dateOfBirth"] copy]; + _context = [dictionary[@"context"] copy]; + _needConfirmation = [dictionary[@"needConfirmation"] boolValue]; + id verifiedProvider = dictionary[@"verifiedProvider"]; + if ([verifiedProvider isKindOfClass:[NSString class]]) { + NSData *data = [verifiedProvider dataUsingEncoding:NSUTF8StringEncoding]; + verifiedProvider = [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableLeaves + error:nil]; + } + if ([verifiedProvider isKindOfClass:[NSArray class]]) { + _verifiedProvider = [[NSArray alloc] initWithArray:verifiedProvider copyItems:YES]; + } + _oauthIDToken = [dictionary[@"oauthIdToken"] copy]; + _oauthExpirationDate = + [dictionary[@"oauthExpireIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"oauthExpireIn"] doubleValue]] + : nil; + _oauthAccessToken = [dictionary[@"oauthAccessToken"] copy]; + _oauthSecretToken = [dictionary[@"oauthTokenSecret"] copy]; + _pendingToken = [dictionary[@"pendingToken"] copy]; + + if (dictionary[@"mfaInfo"] != nil) { + NSMutableArray *MFAInfo = [NSMutableArray array]; + NSArray *MFAInfoDataArray = dictionary[@"mfaInfo"]; + for (NSDictionary *MFAInfoData in MFAInfoDataArray) { + FIRAuthProtoMFAEnrollment *MFAEnrollment = + [[FIRAuthProtoMFAEnrollment alloc] initWithDictionary:MFAInfoData]; + [MFAInfo addObject:MFAEnrollment]; + } + _MFAInfo = MFAInfo; + } + _MFAPendingCredential = [dictionary[@"mfaPendingCredential"] copy]; + + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h new file mode 100644 index 00000000..7b4d3bc9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRVerifyClientRequest : FIRIdentityToolkitRequest + +/** @property appToken + @brief The APNS device token. + */ +@property(nonatomic, readonly, nullable) NSString *appToken; + +/** @property isSandbox + @brief The flag that denotes if the appToken pertains to Sandbox or Production. + */ +@property(nonatomic, assign, readonly) BOOL isSandbox; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithToken:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithAppToken:isSandbox:requestConfiguration: + @brief Designated initializer. + @param appToken The APNS device token. + @param isSandbox The flag indicating whether or not the app token provided is for Sandbox or + Production. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithAppToken:(nullable NSString *)appToken + isSandbox:(BOOL)isSandbox + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.m new file mode 100644 index 00000000..02e984cc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.m @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kVerifyClientEndpoint + @brief The endpoint for the verifyClient request. + */ +static NSString *const kVerifyClientEndpoint = @"verifyClient"; + +/** @var kAppTokenKey + @brief The key for the appToken request paramenter. + */ +static NSString *const kAPPTokenKey = @"appToken"; + +/** @var kIsSandboxKey + @brief The key for the isSandbox request parameter + */ +static NSString *const kIsSandboxKey = @"isSandbox"; + +@implementation FIRVerifyClientRequest + +- (nullable instancetype)initWithAppToken:(nullable NSString *)appToken + isSandbox:(BOOL)isSandbox + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyClientEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _appToken = appToken; + _isSandbox = isSandbox; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_appToken) { + postBody[kAPPTokenKey] = _appToken; + } + if (_isSandbox) { + postBody[kIsSandboxKey] = @YES; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h new file mode 100644 index 00000000..40e69072 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRVerifyClientResponse : NSObject + +/** @property receipt + @brief Receipt that the APNS token was successfully validated with APNS. + */ +@property(nonatomic, copy, readonly, nullable) NSString *receipt; + +/** @property suggestedTimeOut + @brief The date after which delivery of the silent push notification is considered to have + failed. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *suggestedTimeOutDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.m new file mode 100644 index 00000000..78d648c5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.m @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRVerifyClientResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _receipt = dictionary[@"receipt"]; + _suggestedTimeOutDate = + [dictionary[@"suggestedTimeout"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"suggestedTimeout"] doubleValue]] + : nil; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h new file mode 100644 index 00000000..abea35af --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyCustomTokenRequest + @brief Represents the parameters for the verifyCustomToken endpoint. + */ +@interface FIRVerifyCustomTokenRequest : FIRIdentityToolkitRequest + +/** @property token + @brief The self-signed token from the client's BYOAuth server. + */ +@property(nonatomic, copy, readonly) NSString *token; + +/** @property returnSecureToken + @brief Whether the response should return access token and refresh token directly. + @remarks The default value is @c YES . + */ +@property(nonatomic, assign) BOOL returnSecureToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithToken:requestConfiguration: instead. + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithToken:requestConfiguration: + @brief Designated initializer. + @param token The self-signed token from the client's BYOAuth server. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithToken:(NSString *)token + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.m new file mode 100644 index 00000000..63c81f61 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.m @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kVerifyCustomTokenEndpoint + @brief The "verifyPassword" endpoint. + */ +static NSString *const kVerifyCustomTokenEndpoint = @"verifyCustomToken"; + +/** @var kTokenKey + @brief The key for the "token" value in the request. + */ +static NSString *const kTokenKey = @"token"; + +/** @var kReturnSecureTokenKey + @brief The key for the "returnSecureToken" value in the request. + */ +static NSString *const kReturnSecureTokenKey = @"returnSecureToken"; + +@implementation FIRVerifyCustomTokenRequest + +- (nullable instancetype)initWithToken:(NSString *)token + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyCustomTokenEndpoint + requestConfiguration:requestConfiguration]; + if (self) { + _token = [token copy]; + _returnSecureToken = YES; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *body = [@{kTokenKey : _token} mutableCopy]; + if (_returnSecureToken) { + body[kReturnSecureTokenKey] = @YES; + } + return body; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h new file mode 100644 index 00000000..7484a94f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyCustomTokenResponse + @brief Represents the response from the verifyCustomToken endpoint. + */ +@interface FIRVerifyCustomTokenResponse : NSObject + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +/** @property isNewUser + @brief Flag indicating that the user signing in is a new user and not a returning user. + */ +@property(nonatomic, assign) BOOL isNewUser; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.m new file mode 100644 index 00000000..1bbe645a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.m @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRVerifyCustomTokenResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _isNewUser = [dictionary[@"isNewUser"] boolValue]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h new file mode 100644 index 00000000..5931578e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyPasswordRequest + @brief Represents the parameters for the verifyPassword endpoint. + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyPassword + */ +@interface FIRVerifyPasswordRequest : FIRIdentityToolkitRequest + +/** @property email + @brief The email of the user. + */ +@property(nonatomic, copy) NSString *email; + +/** @property password + @brief The password inputed by the user. + */ +@property(nonatomic, copy) NSString *password; + +/** @property pendingIDToken + @brief The GITKit token for the non-trusted IDP, which is to be confirmed by the user. + */ +@property(nonatomic, copy, nullable) NSString *pendingIDToken; + +/** @property captchaChallenge + @brief The captcha challenge. + */ +@property(nonatomic, copy, nullable) NSString *captchaChallenge; + +/** @property captchaResponse + @brief Response to the captcha. + */ +@property(nonatomic, copy, nullable) NSString *captchaResponse; + +/** @property returnSecureToken + @brief Whether the response should return access token and refresh token directly. + @remarks The default value is @c YES . + */ +@property(nonatomic, assign) BOOL returnSecureToken; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithEmail:password:requestConfiguration: + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithEmail:password:requestConfiguration: + @brief Designated initializer. + @param email The email of the user. + @param password The password inputed by the user. + @param requestConfiguration The configu + */ +- (nullable instancetype)initWithEmail:(NSString *)email + password:(NSString *)password + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.m new file mode 100644 index 00000000..03cf490a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.m @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kVerifyPasswordEndpoint + @brief The "verifyPassword" endpoint. + */ +static NSString *const kVerifyPasswordEndpoint = @"verifyPassword"; + +/** @var kEmailKey + @brief The key for the "email" value in the request. + */ +static NSString *const kEmailKey = @"email"; + +/** @var kPasswordKey + @brief The key for the "password" value in the request. + */ +static NSString *const kPasswordKey = @"password"; + +/** @var kPendingIDTokenKey + @brief The key for the "pendingIdToken" value in the request. + */ +static NSString *const kPendingIDTokenKey = @"pendingIdToken"; + +/** @var kCaptchaChallengeKey + @brief The key for the "captchaChallenge" value in the request. + */ +static NSString *const kCaptchaChallengeKey = @"captchaChallenge"; + +/** @var kCaptchaResponseKey + @brief The key for the "captchaResponse" value in the request. + */ +static NSString *const kCaptchaResponseKey = @"captchaResponse"; + +/** @var kReturnSecureTokenKey + @brief The key for the "returnSecureToken" value in the request. + */ +static NSString *const kReturnSecureTokenKey = @"returnSecureToken"; + +@implementation FIRVerifyPasswordRequest + +- (nullable instancetype)initWithEmail:(NSString *)email + password:(NSString *)password + requestConfiguration:(nonnull FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyPasswordEndpoint requestConfiguration:requestConfiguration]; + if (self) { + _email = [email copy]; + _password = [password copy]; + _returnSecureToken = YES; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_email) { + postBody[kEmailKey] = _email; + } + if (_password) { + postBody[kPasswordKey] = _password; + } + if (_pendingIDToken) { + postBody[kPendingIDTokenKey] = _pendingIDToken; + } + if (_captchaChallenge) { + postBody[kCaptchaChallengeKey] = _captchaChallenge; + } + if (_captchaResponse) { + postBody[kCaptchaResponseKey] = _captchaResponse; + } + if (_returnSecureToken) { + postBody[kReturnSecureTokenKey] = @YES; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h new file mode 100644 index 00000000..26563c71 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRVerifyPasswordResponse + @brief Represents the response from the verifyPassword endpoint. + @remarks Possible error codes: + - FIRAuthInternalErrorCodeUserDisabled + - FIRAuthInternalErrorCodeEmailNotFound + @see https://developers.google.com/identity/toolkit/web/reference/relyingparty/verifyPassword + */ +@interface FIRVerifyPasswordResponse : NSObject + +/** @property localID + @brief The RP local ID if it's already been mapped to the IdP account identified by the + federated ID. + */ +@property(nonatomic, strong, readonly, nullable) NSString *localID; + +/** @property email + @brief The email returned by the IdP. NOTE: The federated login user may not own the email. + */ +@property(nonatomic, strong, readonly, nullable) NSString *email; + +/** @property displayName + @brief The display name of the user. + */ +@property(nonatomic, strong, readonly, nullable) NSString *displayName; + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +/** @property photoURL + @brief The URI of the public accessible profile picture. + */ +@property(nonatomic, strong, readonly, nullable) NSURL *photoURL; + +@property(nonatomic, strong, readonly, nullable) NSString *MFAPendingCredential; + +@property(nonatomic, strong, readonly, nullable) NSArray *MFAInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.m new file mode 100644 index 00000000..df8208f6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.m @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRVerifyPasswordResponse + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _localID = [dictionary[@"localId"] copy]; + _email = [dictionary[@"email"] copy]; + _displayName = [dictionary[@"displayName"] copy]; + _IDToken = [dictionary[@"idToken"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _photoURL = dictionary[@"photoUrl"] ? [NSURL URLWithString:dictionary[@"photoUrl"]] : nil; + + if (dictionary[@"mfaInfo"] != nil) { + NSMutableArray *MFAInfo = [NSMutableArray array]; + NSArray *MFAInfoDataArray = dictionary[@"mfaInfo"]; + for (NSDictionary *MFAInfoData in MFAInfoDataArray) { + FIRAuthProtoMFAEnrollment *MFAEnrollment = + [[FIRAuthProtoMFAEnrollment alloc] initWithDictionary:MFAInfoData]; + [MFAInfo addObject:MFAEnrollment]; + } + _MFAInfo = MFAInfo; + } + _MFAPendingCredential = [dictionary[@"mfaPendingCredential"] copy]; + + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h new file mode 100644 index 00000000..da8d4e87 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h @@ -0,0 +1,90 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Auth/FIRAuthOperationType.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRVerifyPhoneNumberRequest : FIRIdentityToolkitRequest + +/** @property verificationID + @brief The verification ID obtained from the response of @c sendVerificationCode. +*/ +@property(nonatomic, readonly, nullable) NSString *verificationID; + +/** @property verificationCode + @brief The verification code provided by the user. +*/ +@property(nonatomic, readonly, nullable) NSString *verificationCode; + +/** @property accessToken + @brief The STS Access Token for the authenticated user. + */ +@property(nonatomic, copy, nullable) NSString *accessToken; + +/** @var temporaryProof + @brief The temporary proof code, previously returned from the backend. + */ +@property(nonatomic, readonly, nonnull) NSString *temporaryProof; + +/** @var phoneNumber + @brief The phone number to be verified in the request. + */ +@property(nonatomic, readonly, nonnull) NSString *phoneNumber; + +/** @var operation + @brief The type of operation triggering this verify phone number request. + */ +@property(nonatomic, assign, readonly) FIRAuthOperationType operation; + +/** @fn initWithEndpoint:requestConfiguration: + @brief Please use initWithVerificationID:verificationCode:requestConfiguration + */ +- (nullable instancetype)initWithEndpoint:(NSString *)endpoint + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_UNAVAILABLE; + +/** @fn initWithTemporaryProof:phoneNumberAPIKey + @brief Designated initializer. + @param temporaryProof The temporary proof sent by the backed. + @param phoneNumber The phone number associated with the credential to be signed in. + @param operation Indicates what operation triggered the verify phone number request. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithTemporaryProof:(NSString *)temporaryProof + phoneNumber:(NSString *)phoneNumber + operation:(FIRAuthOperationType)operation + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +/** @fn initWithVerificationID:verificationCode:requestConfiguration + @brief Designated initializer. + @param verificationID The verification ID obtained from the response of @c sendVerificationCode. + @param verificationCode The verification code provided by the user. + @param operation Indicates what operation triggered the verify phone number request. + @param requestConfiguration An object containing configurations to be added to the request. + */ +- (nullable instancetype)initWithVerificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode + operation:(FIRAuthOperationType)operation + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.m new file mode 100644 index 00000000..e2ee9166 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.m @@ -0,0 +1,133 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kVerifyPhoneNumberEndPoint + @brief The "verifyPhoneNumber" endpoint. + */ +static NSString *const kVerifyPhoneNumberEndPoint = @"verifyPhoneNumber"; + +/** @var kVerificationIDKey + @brief The key for the verification ID parameter in the request. + */ +static NSString *const kVerificationIDKey = @"sessionInfo"; + +/** @var kVerificationCodeKey + @brief The key for the verification code parameter in the request. + */ +static NSString *const kVerificationCodeKey = @"code"; + +/** @var kIDTokenKey + @brief The key for the "ID Token" value in the request. + */ +static NSString *const kIDTokenKey = @"idToken"; + +/** @var kTemporaryProofKey + @brief The key for the temporary proof value in the request. + */ +static NSString *const kTemporaryProofKey = @"temporaryProof"; + +/** @var kPhoneNumberKey + @brief The key for the phone number value in the request. + */ +static NSString *const kPhoneNumberKey = @"phoneNumber"; + +/** @var kOperationKey + @brief The key for the operation value in the request. + */ +static NSString *const kOperationKey = @"operation"; + +@implementation FIRVerifyPhoneNumberRequest + +- (nullable instancetype)initWithTemporaryProof:(NSString *)temporaryProof + phoneNumber:(NSString *)phoneNumber + operation:(FIRAuthOperationType)operation + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyPhoneNumberEndPoint + requestConfiguration:requestConfiguration]; + if (self) { + _temporaryProof = [temporaryProof copy]; + _phoneNumber = [phoneNumber copy]; + _operation = operation; + } + return self; +} + +- (nullable instancetype)initWithVerificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode + operation:(FIRAuthOperationType)operation + requestConfiguration: + (FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kVerifyPhoneNumberEndPoint + requestConfiguration:requestConfiguration]; + if (self) { + _verificationID = verificationID; + _verificationCode = verificationCode; + _operation = operation; + } + return self; +} + +/** @fn FIRAuthOperationString + @brief Returns a string object corresponding to the provided FIRAuthOperationType value. + @param operationType The value of the FIRAuthOperationType enum which will be translated to its + corresponding string value. + @return The string value corresponding to the FIRAuthOperationType argument. + */ +NSString *const FIRAuthOperationString(FIRAuthOperationType operationType) { + switch (operationType) { + case FIRAuthOperationTypeUnspecified: + return @"VERIFY_OP_UNSPECIFIED"; + case FIRAuthOperationTypeSignUpOrSignIn: + return @"SIGN_UP_OR_IN"; + case FIRAuthOperationTypeReauth: + return @"REAUTH"; + case FIRAuthOperationTypeLink: + return @"LINK"; + case FIRAuthOperationTypeUpdate: + return @"UPDATE"; + } +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_verificationID) { + postBody[kVerificationIDKey] = _verificationID; + } + if (_verificationCode) { + postBody[kVerificationCodeKey] = _verificationCode; + } + if (_accessToken) { + postBody[kIDTokenKey] = _accessToken; + } + if (_temporaryProof) { + postBody[kTemporaryProofKey] = _temporaryProof; + } + if (_phoneNumber) { + postBody[kPhoneNumberKey] = _phoneNumber; + } + NSString *operation = FIRAuthOperationString(_operation); + postBody[kOperationKey] = operation; + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h new file mode 100644 index 00000000..7817ccf0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRVerifyPhoneNumberResponse : NSObject + +/** @property IDToken + @brief Either an authorization code suitable for performing an STS token exchange, or the + access token from Secure Token Service, depending on whether @c returnSecureToken is set + on the request. + */ +@property(nonatomic, strong, readonly, nullable) NSString *IDToken; + +/** @property refreshToken + @brief The refresh token from Secure Token Service. + */ +@property(nonatomic, strong, readonly, nullable) NSString *refreshToken; + +/** @property localID + @brief The Firebase Auth user ID. + */ +@property(nonatomic, strong, readonly, nullable) NSString *localID; + +/** @property phoneNumber + @brief The verified phone number. + */ +@property(nonatomic, strong, readonly, nullable) NSString *phoneNumber; + +/** @property temporaryProof + @brief The temporary proof code returned by the backend. + */ +@property(nonatomic, strong, readonly, nullable) NSString *temporaryProof; + +/** @property isNewUser + @brief Flag indicating that the user signing in is a new user and not a returning user. + */ +@property(nonatomic, assign) BOOL isNewUser; + +/** @property approximateExpirationDate + @brief The approximate expiration date of the access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *approximateExpirationDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.m new file mode 100644 index 00000000..902fb967 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.m @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRVerifyPhoneNumberResponse + +- (nullable NSString *)expectedKind { + return nil; +} + +- (BOOL)setWithDictionary:(NSDictionary *)dictionary error:(NSError *_Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + _isNewUser = [dictionary[@"isNewUser"] boolValue]; + _localID = [dictionary[@"localId"] copy]; + _phoneNumber = [dictionary[@"phoneNumber"] copy]; + _temporaryProof = [dictionary[@"temporaryProof"] copy]; + _approximateExpirationDate = + [dictionary[@"expiresIn"] isKindOfClass:[NSString class]] + ? [NSDate dateWithTimeIntervalSinceNow:[dictionary[@"expiresIn"] doubleValue]] + : nil; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h new file mode 100644 index 00000000..edd8a732 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFinalizeMFAEnrollmentRequest : FIRIdentityToolkitRequest + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) NSString *displayName; + +@property(nonatomic, copy, readonly, nullable) + FIRAuthProtoFinalizeMFAPhoneRequestInfo *verificationInfo; + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + displayName:(NSString *)displayName + verificationInfo:(FIRAuthProtoFinalizeMFAPhoneRequestInfo *)verificationInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.m new file mode 100644 index 00000000..3874a8f9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.m @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h" + +static NSString *const kFinalizeMFAEnrollmentEndPoint = @"accounts/mfaEnrollment:finalize"; + +@implementation FIRFinalizeMFAEnrollmentRequest + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + displayName:(NSString *)displayName + verificationInfo:(FIRAuthProtoFinalizeMFAPhoneRequestInfo *)verificationInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kFinalizeMFAEnrollmentEndPoint + requestConfiguration:requestConfiguration + useIdentityPlatform:YES + useStaging:NO]; + if (self) { + _IDToken = IDToken; + _displayName = displayName; + _verificationInfo = verificationInfo; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_IDToken) { + postBody[@"idToken"] = _IDToken; + } + if (_displayName) { + postBody[@"displayName"] = _displayName; + } + if (_verificationInfo) { + if ([_verificationInfo isKindOfClass:[FIRAuthProtoFinalizeMFAPhoneRequestInfo class]]) { + postBody[@"phoneVerificationInfo"] = [_verificationInfo dictionary]; + } + } + return [postBody copy]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h new file mode 100644 index 00000000..aca12a17 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFinalizeMFAEnrollmentResponse : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.m new file mode 100644 index 00000000..1e9cac5b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.m @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h" + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h" + +@implementation FIRFinalizeMFAEnrollmentResponse + +- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary + error:(NSError *__autoreleasing _Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h new file mode 100644 index 00000000..62599f6d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStartMFAEnrollmentRequest : FIRIdentityToolkitRequest + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) FIRAuthProtoStartMFAPhoneRequestInfo *enrollmentInfo; + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + enrollmentInfo:(FIRAuthProtoStartMFAPhoneRequestInfo *)enrollmentInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.m new file mode 100644 index 00000000..977c1b71 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.m @@ -0,0 +1,52 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h" + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h" + +static NSString *const kStartMFAEnrollmentEndPoint = @"accounts/mfaEnrollment:start"; + +@implementation FIRStartMFAEnrollmentRequest + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + enrollmentInfo:(FIRAuthProtoStartMFAPhoneRequestInfo *)enrollmentInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kStartMFAEnrollmentEndPoint + requestConfiguration:requestConfiguration + useIdentityPlatform:YES + useStaging:NO]; + if (self) { + _IDToken = IDToken; + _enrollmentInfo = enrollmentInfo; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_IDToken) { + postBody[@"idToken"] = _IDToken; + } + if (_enrollmentInfo) { + if ([_enrollmentInfo isKindOfClass:[FIRAuthProtoStartMFAPhoneRequestInfo class]]) { + postBody[@"phoneEnrollmentInfo"] = [_enrollmentInfo dictionary]; + } + } + return [postBody copy]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h new file mode 100644 index 00000000..d0d5bdaa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStartMFAEnrollmentResponse : NSObject + +@property(nonatomic, copy, readonly, nullable) + FIRAuthProtoStartMFAPhoneResponseInfo *enrollmentResponse; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.m new file mode 100644 index 00000000..658462ce --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.m @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h" + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h" + +@implementation FIRStartMFAEnrollmentResponse + +- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary + error:(NSError *__autoreleasing _Nullable *_Nullable)error { + if (dictionary[@"phoneSessionInfo"] != nil) { + NSDictionary *data = dictionary[@"phoneSessionInfo"]; + _enrollmentResponse = [[FIRAuthProtoStartMFAPhoneResponseInfo alloc] initWithDictionary:data]; + } else { + return NO; + } + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h new file mode 100644 index 00000000..155f5ea7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFinalizeMFASignInRequest : FIRIdentityToolkitRequest + +@property(nonatomic, copy, readonly, nullable) NSString *MFAPendingCredential; + +@property(nonatomic, copy, readonly, nullable) + FIRAuthProtoFinalizeMFAPhoneRequestInfo *verificationInfo; + +- (nullable instancetype) + initWithMFAPendingCredential:(NSString *)MFAPendingCredential + verificationInfo:(FIRAuthProtoFinalizeMFAPhoneRequestInfo *)verificationInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.m new file mode 100644 index 00000000..65fe3158 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.m @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h" + +static NSString *const kFinalizeMFASignInEndPoint = @"accounts/mfaSignIn:finalize"; + +@implementation FIRFinalizeMFASignInRequest + +- (nullable instancetype) + initWithMFAPendingCredential:(NSString *)MFAPendingCredential + verificationInfo:(FIRAuthProtoFinalizeMFAPhoneRequestInfo *)verificationInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kFinalizeMFASignInEndPoint + requestConfiguration:requestConfiguration + useIdentityPlatform:YES + useStaging:NO]; + if (self) { + _MFAPendingCredential = MFAPendingCredential; + _verificationInfo = verificationInfo; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_MFAPendingCredential) { + postBody[@"mfaPendingCredential"] = _MFAPendingCredential; + } + if (_verificationInfo) { + if ([_verificationInfo isKindOfClass:[FIRAuthProtoFinalizeMFAPhoneRequestInfo class]]) { + postBody[@"phoneVerificationInfo"] = [_verificationInfo dictionary]; + } + } + return [postBody copy]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h new file mode 100644 index 00000000..5ad8bd69 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRFinalizeMFASignInResponse : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.m new file mode 100644 index 00000000..0763880a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.m @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h" + +@implementation FIRFinalizeMFASignInResponse + +- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary + error:(NSError *__autoreleasing _Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h new file mode 100644 index 00000000..8a12bad2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStartMFASignInRequest : FIRIdentityToolkitRequest + +@property(nonatomic, copy, readonly, nullable) NSString *MFAPendingCredential; + +@property(nonatomic, copy, readonly, nullable) NSString *MFAEnrollmentID; + +@property(nonatomic, copy, readonly, nullable) FIRAuthProtoStartMFAPhoneRequestInfo *signInInfo; + +- (nullable instancetype) + initWithMFAPendingCredential:(NSString *)MFAPendingCredential + MFAEnrollmentID:(NSString *)MFAEnrollmentID + signInInfo:(FIRAuthProtoStartMFAPhoneRequestInfo *)signInInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.m new file mode 100644 index 00000000..0ba4876a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.m @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h" + +static NSString *const kStartMFASignInEndPoint = @"accounts/mfaSignIn:start"; + +@implementation FIRStartMFASignInRequest + +- (nullable instancetype) + initWithMFAPendingCredential:(NSString *)MFAPendingCredential + MFAEnrollmentID:(NSString *)MFAEnrollmentID + signInInfo:(FIRAuthProtoStartMFAPhoneRequestInfo *)signInInfo + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kStartMFASignInEndPoint + requestConfiguration:requestConfiguration + useIdentityPlatform:YES + useStaging:NO]; + if (self) { + _MFAPendingCredential = MFAPendingCredential; + _MFAEnrollmentID = MFAEnrollmentID; + _signInInfo = signInInfo; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_MFAPendingCredential) { + postBody[@"mfaPendingCredential"] = _MFAPendingCredential; + } + if (_MFAEnrollmentID) { + postBody[@"mfaEnrollmentId"] = _MFAEnrollmentID; + } + if (_signInInfo) { + if ([_signInInfo isKindOfClass:[FIRAuthProtoStartMFAPhoneRequestInfo class]]) { + postBody[@"phoneSignInInfo"] = [_signInInfo dictionary]; + } + } + return [postBody copy]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h new file mode 100644 index 00000000..bd1c372e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStartMFASignInResponse : NSObject + +@property(nonatomic, copy, readonly, nullable) FIRAuthProtoStartMFAPhoneResponseInfo *responseInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.m new file mode 100644 index 00000000..7ad49f85 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.m @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h" + +@implementation FIRStartMFASignInResponse + +- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary + error:(NSError *__autoreleasing _Nullable *_Nullable)error { + if (dictionary[@"phoneResponseInfo"] != nil) { + NSDictionary *data = dictionary[@"phoneResponseInfo"]; + _responseInfo = [[FIRAuthProtoStartMFAPhoneResponseInfo alloc] initWithDictionary:data]; + } else { + return NO; + } + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h new file mode 100644 index 00000000..df211f80 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h" +#import "FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRWithdrawMFARequest : FIRIdentityToolkitRequest + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) NSString *MFAEnrollmentID; + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + MFAEnrollmentID:(NSString *)MFAEnrollmentID + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.m new file mode 100644 index 00000000..f4468e39 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.m @@ -0,0 +1,52 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const kWithdrawMFAEndPoint = @"accounts/mfaEnrollment:withdraw"; + +@implementation FIRWithdrawMFARequest + +- (nullable instancetype)initWithIDToken:(NSString *)IDToken + MFAEnrollmentID:(NSString *)MFAEnrollmentID + requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration { + self = [super initWithEndpoint:kWithdrawMFAEndPoint + requestConfiguration:requestConfiguration + useIdentityPlatform:YES + useStaging:NO]; + if (self) { + _IDToken = IDToken; + _MFAEnrollmentID = MFAEnrollmentID; + } + return self; +} + +- (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { + NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; + if (_IDToken) { + postBody[@"idToken"] = _IDToken; + } + if (_MFAEnrollmentID) { + postBody[@"mfaEnrollmentId"] = _MFAEnrollmentID; + } + return [postBody copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h new file mode 100644 index 00000000..84adf824 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRWithdrawMFAResponse : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *IDToken; + +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.m new file mode 100644 index 00000000..7d1c3c76 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.m @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRWithdrawMFAResponse + +- (BOOL)setWithDictionary:(nonnull NSDictionary *)dictionary + error:(NSError *__autoreleasing _Nullable *_Nullable)error { + _IDToken = [dictionary[@"idToken"] copy]; + _refreshToken = [dictionary[@"refreshToken"] copy]; + return YES; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h new file mode 100644 index 00000000..5d0d8616 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol FIRAuthProto + +@optional +- (instancetype)initWithDictionary:(NSDictionary *)dictionary; + +- (NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h new file mode 100644 index 00000000..4246e62f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthProtoMFAEnrollment : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *MFAValue; + +@property(nonatomic, copy, readonly, nullable) NSString *MFAEnrollmentID; + +@property(nonatomic, copy, readonly, nullable) NSString *displayName; + +@property(nonatomic, copy, readonly, nullable) NSDate *enrolledAt; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.m new file mode 100644 index 00000000..92237e9b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.m @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthProtoMFAEnrollment + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + if (dictionary[@"phoneInfo"]) { + _MFAValue = dictionary[@"phoneInfo"]; + } + _MFAEnrollmentID = dictionary[@"mfaEnrollmentId"]; + _displayName = dictionary[@"displayName"]; + if ([dictionary[@"enrolledAt"] isKindOfClass:[NSString class]]) { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; + NSDate *date = [dateFormatter dateFromString:dictionary[@"enrolledAt"]]; + _enrolledAt = date; + } + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h new file mode 100644 index 00000000..df6e39af --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthProtoFinalizeMFAPhoneRequestInfo : NSObject + +@property(nonatomic, strong, readonly, nullable) NSString *sessionInfo; + +@property(nonatomic, strong, readonly, nullable) NSString *code; + +- (instancetype)initWithSessionInfo:(NSString *)sessionInfo + verificationCode:(NSString *)verificationCode; +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.m new file mode 100644 index 00000000..b233a137 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthProtoFinalizeMFAPhoneRequestInfo + +- (instancetype)initWithSessionInfo:(NSString *)sessionInfo + verificationCode:(NSString *)verificationCode { + self = [super init]; + if (self) { + _sessionInfo = sessionInfo; + _code = verificationCode; + } + return self; +} + +- (NSDictionary *)dictionary { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (_sessionInfo) { + dict[@"sessionInfo"] = _sessionInfo; + } + if (_code) { + dict[@"code"] = _code; + } + return [dict copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h new file mode 100644 index 00000000..fc9af6ec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthProtoFinalizeMFAPhoneResponseInfo : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *phoneNumber; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.m new file mode 100644 index 00000000..f8f1d96e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.m @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthProtoFinalizeMFAPhoneResponseInfo + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _phoneNumber = [dictionary[@"phoneNumber"] copy]; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h new file mode 100644 index 00000000..e17315fa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthProtoStartMFAPhoneRequestInfo : NSObject + +@property(nonatomic, strong, readonly, nullable) NSString *phoneNumber; + +@property(nonatomic, strong, readonly, nullable) FIRAuthAppCredential *appCredential; + +@property(nonatomic, strong, readonly, nullable) NSString *reCAPTCHAToken; + +- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber + appCredential:(nullable FIRAuthAppCredential *)appCredential + reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.m new file mode 100644 index 00000000..1c0ffeaa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.m @@ -0,0 +1,74 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kPhoneNumberKey + @brief The key for the Phone Number parameter in the request. + */ +static NSString *const kPhoneNumberKey = @"phoneNumber"; + +/** @var kReceiptKey + @brief The key for the receipt parameter in the request. + */ +static NSString *const kReceiptKey = @"iosReceipt"; + +/** @var kSecretKey + @brief The key for the Secret parameter in the request. + */ +static NSString *const kSecretKey = @"iosSecret"; + +/** @var kreCAPTCHATokenKey + @brief The key for the reCAPTCHAToken parameter in the request. + */ +static NSString *const kreCAPTCHATokenKey = @"recaptchaToken"; + +@implementation FIRAuthProtoStartMFAPhoneRequestInfo + +- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber + appCredential:(nullable FIRAuthAppCredential *)appCredential + reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken { + self = [super init]; + if (self) { + _phoneNumber = [phoneNumber copy]; + _appCredential = appCredential; + _reCAPTCHAToken = [reCAPTCHAToken copy]; + } + return self; +} + +- (NSDictionary *)dictionary { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (_phoneNumber) { + dict[kPhoneNumberKey] = _phoneNumber; + } + if (_appCredential.receipt) { + dict[kReceiptKey] = _appCredential.receipt; + } + if (_appCredential.secret) { + dict[kSecretKey] = _appCredential.secret; + } + if (_reCAPTCHAToken) { + dict[kreCAPTCHATokenKey] = _reCAPTCHAToken; + } + return [dict copy]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h new file mode 100644 index 00000000..1cdb6903 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthProtoStartMFAPhoneResponseInfo : NSObject + +@property(nonatomic, copy, readonly, nullable) NSString *sessionInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.m new file mode 100644 index 00000000..065e4178 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.m @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthProtoStartMFAPhoneResponseInfo + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _sessionInfo = [dictionary[@"sessionInfo"] copy]; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/FirebaseAuthVersion.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/FirebaseAuthVersion.m new file mode 100644 index 00000000..75d32e94 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/FirebaseAuthVersion.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const double FirebaseAuthVersionNum = FIRAuth_MINOR_VERSION; + +const char *const FirebaseAuthVersionStr = (const char *const)STR(FIRAuth_VERSION); diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h new file mode 100644 index 00000000..56b49aab --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRMultiFactor () + +@property(nonatomic, weak) FIRUser *user; + +/** @fn initWithMFAEnrollments: + @brief Initialize a multi factor instance with a list of MFA enrollments. +*/ +- (instancetype)initWithMFAEnrollments:(NSArray *)MFAEnrollments; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor.m new file mode 100644 index 00000000..838b1b5b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactor.m @@ -0,0 +1,195 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h" +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h" +#import "FirebaseAuth/Sources/User/FIRUser_Internal.h" + +#if TARGET_OS_IOS +#import + +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +static NSString *kEnrolledFactorsCodingKey = @"enrolledFactors"; + +static NSString *kUserCodingKey = @"user"; + +@implementation FIRMultiFactor + +- (void)getSessionWithCompletion:(nullable FIRMultiFactorSessionCallback)completion { + FIRMultiFactorSession *session = [FIRMultiFactorSession sessionForCurrentUser]; + if (completion) { + completion(session, nil); + } +} + +- (void)enrollWithAssertion:(FIRMultiFactorAssertion *)assertion + displayName:(nullable NSString *)displayName + completion:(nullable FIRAuthVoidErrorCallback)completion { +#if TARGET_OS_IOS + FIRPhoneMultiFactorAssertion *phoneAssertion = (FIRPhoneMultiFactorAssertion *)assertion; + FIRAuthProtoFinalizeMFAPhoneRequestInfo *finalizeMFAPhoneRequestInfo = + [[FIRAuthProtoFinalizeMFAPhoneRequestInfo alloc] + initWithSessionInfo:phoneAssertion.authCredential.verificationID + verificationCode:phoneAssertion.authCredential.verificationCode]; + FIRFinalizeMFAEnrollmentRequest *request = + [[FIRFinalizeMFAEnrollmentRequest alloc] initWithIDToken:self.user.rawAccessToken + displayName:displayName + verificationInfo:finalizeMFAPhoneRequestInfo + requestConfiguration:self.user.requestConfiguration]; + [FIRAuthBackend + finalizeMultiFactorEnrollment:request + callback:^(FIRFinalizeMFAEnrollmentResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (completion) { + completion(error); + } + } else { + [FIRAuth.auth + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:nil + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + FIRAuthDataResult *result = + [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:nil]; + FIRAuthDataResultCallback + decoratedCallback = [FIRAuth.auth + signInFlowAuthDataResultCallbackByDecoratingCallback: + ^(FIRAuthDataResult + *_Nullable authResult, + NSError *_Nullable error) { + if (completion) { + completion(error); + } + }]; + decoratedCallback(result, error); + }]; + } + }]; +#endif +} + +- (void)unenrollWithInfo:(FIRMultiFactorInfo *)factorInfo + completion:(nullable FIRAuthVoidErrorCallback)completion { + [self unenrollWithFactorUID:factorInfo.UID completion:completion]; +} + +- (void)unenrollWithFactorUID:(NSString *)factorUID + completion:(nullable FIRAuthVoidErrorCallback)completion { + FIRWithdrawMFARequest *request = + [[FIRWithdrawMFARequest alloc] initWithIDToken:self.user.rawAccessToken + MFAEnrollmentID:factorUID + requestConfiguration:self.user.requestConfiguration]; + [FIRAuthBackend + withdrawMultiFactor:request + callback:^(FIRWithdrawMFAResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + if (completion) { + completion(error); + } + } else { + [FIRAuth.auth + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:nil + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + FIRAuthDataResult *result = + [[FIRAuthDataResult alloc] initWithUser:user + additionalUserInfo:nil]; + FIRAuthDataResultCallback decoratedCallback = [FIRAuth + .auth + signInFlowAuthDataResultCallbackByDecoratingCallback: + ^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + if (error) { + [[FIRAuth auth] signOut:NULL]; + } + if (completion) { + completion(error); + } + }]; + decoratedCallback(result, error); + }]; + } + }]; +} + +#pragma mark - Internal + +- (instancetype)initWithMFAEnrollments:(NSArray *)MFAEnrollments { + self = [super init]; + + if (self) { + NSMutableArray *multiFactorInfoArray = [[NSMutableArray alloc] init]; + for (FIRAuthProtoMFAEnrollment *MFAEnrollment in MFAEnrollments) { + FIRMultiFactorInfo *multiFactorInfo = + [[FIRMultiFactorInfo alloc] initWithProto:MFAEnrollment]; + [multiFactorInfoArray addObject:multiFactorInfo]; + } + _enrolledFactors = [multiFactorInfoArray copy]; + } + + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [self init]; + if (self) { + NSArray *enrolledFactors = + [aDecoder decodeObjectOfClass:[NSArray class] + forKey:kEnrolledFactorsCodingKey]; + _enrolledFactors = enrolledFactors; + _user = [aDecoder decodeObjectOfClass:[FIRUser class] forKey:kUserCodingKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_enrolledFactors forKey:kEnrolledFactorsCodingKey]; + [aCoder encodeObject:_user forKey:kUserCodingKey]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion+Internal.h new file mode 100644 index 00000000..10065937 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion+Internal.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRMultiFactorAssertion () { + @protected + NSString *_factorID; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion.m new file mode 100644 index 00000000..4a462320 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion.m @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRMultiFactorAssertion +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorConstants.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorConstants.m new file mode 100644 index 00000000..22d299db --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorConstants.m @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#pragma mark - Multi Factor ID constants + +NSString *const FIRPhoneMultiFactorID = @"1"; + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h new file mode 100644 index 00000000..84232930 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRMultiFactorInfo () { + @protected + NSString *_factorID; +} + +- (instancetype)initWithProto:(FIRAuthProtoMFAEnrollment *)proto; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo.m new file mode 100644 index 00000000..fe7e4afc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo.m @@ -0,0 +1,74 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" + +static NSString *kUIDCodingKey = @"uid"; + +static NSString *kDisplayNameCodingKey = @"displayName"; + +static NSString *kEnrollmentDateCodingKey = @"enrollmentDate"; + +static NSString *kFactorIDCodingKey = @"factorID"; + +@implementation FIRMultiFactorInfo + +#pragma mark - Internal + +- (instancetype)initWithProto:(FIRAuthProtoMFAEnrollment *)proto { + self = [super init]; + + if (self) { + _UID = proto.MFAEnrollmentID; + _displayName = proto.displayName; + _enrollmentDate = proto.enrolledAt; + } + + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [self init]; + if (self) { + _UID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUIDCodingKey]; + _displayName = [aDecoder decodeObjectOfClass:[NSString class] forKey:kDisplayNameCodingKey]; + _enrollmentDate = [aDecoder decodeObjectOfClass:[NSDate class] forKey:kEnrollmentDateCodingKey]; + _factorID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kFactorIDCodingKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_UID forKey:kUIDCodingKey]; + [aCoder encodeObject:_displayName forKey:kDisplayNameCodingKey]; + [aCoder encodeObject:_enrollmentDate forKey:kEnrollmentDateCodingKey]; + [aCoder encodeObject:_factorID forKey:kFactorIDCodingKey]; +} + +@end + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h new file mode 100644 index 00000000..c28d6696 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRMultiFactorResolver () + +@property(nonatomic) NSString *MFAPendingCredential; + +- (instancetype)initWithMFAPendingCredential:(NSString *_Nullable)MFAPendingCredential + hints:(NSArray *)hints; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver.m new file mode 100644 index 00000000..4153f413 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver.m @@ -0,0 +1,101 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#if TARGET_OS_IOS + +#import +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h" +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h" +#import "FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h" + +#if TARGET_OS_IOS +#import + +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRMultiFactorResolver + +- (instancetype)initWithMFAPendingCredential:(NSString *_Nullable)MFAPendingCredential + hints:(NSArray *)hints { + self = [super init]; + if (self) { + _MFAPendingCredential = MFAPendingCredential; + _hints = hints; + _auth = [FIRAuth auth]; + _session = [[FIRMultiFactorSession alloc] init]; + _session.MFAPendingCredential = MFAPendingCredential; + } + return self; +} + +- (void)resolveSignInWithAssertion:(nonnull FIRMultiFactorAssertion *)assertion + completion:(nullable FIRAuthDataResultCallback)completion { +#if TARGET_OS_IOS + FIRPhoneMultiFactorAssertion *phoneAssertion = (FIRPhoneMultiFactorAssertion *)assertion; + FIRAuthProtoFinalizeMFAPhoneRequestInfo *finalizeMFAPhoneRequestInfo = + [[FIRAuthProtoFinalizeMFAPhoneRequestInfo alloc] + initWithSessionInfo:phoneAssertion.authCredential.verificationID + verificationCode:phoneAssertion.authCredential.verificationCode]; + FIRFinalizeMFASignInRequest *request = [[FIRFinalizeMFASignInRequest alloc] + initWithMFAPendingCredential:self.MFAPendingCredential + verificationInfo:finalizeMFAPhoneRequestInfo + requestConfiguration:self.auth.requestConfiguration]; + [FIRAuthBackend + finalizeMultiFactorSignIn:request + callback:^(FIRFinalizeMFASignInResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + if (completion) { + completion(nil, error); + } + } else { + [FIRAuth.auth + completeSignInWithAccessToken:response.IDToken + accessTokenExpirationDate:nil + refreshToken:response.refreshToken + anonymous:NO + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + FIRAuthDataResult *result = + [[FIRAuthDataResult alloc] + initWithUser:user + additionalUserInfo:nil]; + FIRAuthDataResultCallback decoratedCallback = + [FIRAuth.auth + signInFlowAuthDataResultCallbackByDecoratingCallback: + completion]; + decoratedCallback(result, error); + }]; + } + }]; +#endif +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h new file mode 100644 index 00000000..e4cf0d4c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRMultiFactorSession () + +@property(nonatomic, readonly) NSString *IDToken; + +@property(nonatomic) NSString *MFAPendingCredential; + +@property(nonatomic) FIRMultiFactorInfo *multiFactorInfo; + ++ (FIRMultiFactorSession *)sessionForCurrentUser; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession.m new file mode 100644 index 00000000..ab1439a7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession.m @@ -0,0 +1,52 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#if TARGET_OS_IOS + +#import +#import + +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h" +#import "FirebaseAuth/Sources/User/FIRUser_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRMultiFactorSession + +#pragma mark - Private + +- (instancetype)initWithIDToken:(NSString *)IDToken { + self = [super init]; + if (self) { + _IDToken = IDToken; + } + return self; +} + +#pragma mark - Internal + ++ (FIRMultiFactorSession *)sessionForCurrentUser { + FIRUser *currentUser = [[FIRAuth auth] currentUser]; + NSString *IDToken = currentUser.rawAccessToken; + FIRMultiFactorSession *session = [[FIRMultiFactorSession alloc] initWithIDToken:IDToken]; + return session; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h new file mode 100644 index 00000000..82a5aca3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRPhoneMultiFactorAssertion () + +@property(nonatomic) FIRPhoneAuthCredential *authCredential; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion.m new file mode 100644 index 00000000..2ad2d1f5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion.m @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion+Internal.h" +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const _Nonnull FIRPhoneMultiFactorID; + +@implementation FIRPhoneMultiFactorAssertion + +- (instancetype)init { + self = [super init]; + if (self) { + _factorID = FIRPhoneMultiFactorID; + } + return self; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorGenerator.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorGenerator.m new file mode 100644 index 00000000..3845083c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorGenerator.m @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +#import "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h" + +@implementation FIRPhoneMultiFactorGenerator + ++ (FIRPhoneMultiFactorAssertion *)assertionWithCredential: + (FIRPhoneAuthCredential *)phoneAuthCredential { + FIRPhoneMultiFactorAssertion *assertion = [[FIRPhoneMultiFactorAssertion alloc] init]; + assertion.authCredential = phoneAuthCredential; + return assertion; +} + +@end + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h new file mode 100644 index 00000000..e4181999 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +@class FIRAuthProtoMFAEnrollment; + +@interface FIRPhoneMultiFactorInfo () + +- (instancetype)initWithProto:(FIRAuthProtoMFAEnrollment *)proto; + +@end + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo.m new file mode 100644 index 00000000..0b9c455c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo.m @@ -0,0 +1,41 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +#import "FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h" + +extern NSString *const FIRPhoneMultiFactorID; + +@implementation FIRPhoneMultiFactorInfo + +- (instancetype)initWithProto:(FIRAuthProtoMFAEnrollment *)proto { + self = [super initWithProto:proto]; + if (self) { + _factorID = FIRPhoneMultiFactorID; + _phoneNumber = proto.MFAValue; + } + return self; +} + +@end + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRActionCodeSettings.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRActionCodeSettings.h new file mode 100644 index 00000000..5024bd59 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRActionCodeSettings.h @@ -0,0 +1,89 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRActionCodeSettings + @brief Used to set and retrieve settings related to handling action codes. + */ +NS_SWIFT_NAME(ActionCodeSettings) +@interface FIRActionCodeSettings : NSObject + +/** @property URL + @brief This URL represents the state/Continue URL in the form of a universal link. + @remarks This URL can should be constructed as a universal link that would either directly open + the app where the action code would be handled or continue to the app after the action code + is handled by Firebase. + */ +@property(nonatomic, copy, nullable) NSURL *URL; + +/** @property handleCodeInApp + @brief Indicates whether the action code link will open the app directly or after being + redirected from a Firebase owned web widget. + */ +@property(assign, nonatomic) BOOL handleCodeInApp; + +/** @property iOSBundleID + @brief The iOS bundle ID, if available. The default value is the current app's bundle ID. + */ +@property(copy, nonatomic, readonly, nullable) NSString *iOSBundleID; + +/** @property androidPackageName + @brief The Android package name, if available. + */ +@property(nonatomic, copy, readonly, nullable) NSString *androidPackageName; + +/** @property androidMinimumVersion + @brief The minimum Android version supported, if available. + */ +@property(nonatomic, copy, readonly, nullable) NSString *androidMinimumVersion; + +/** @property androidInstallIfNotAvailable + @brief Indicates whether the Android app should be installed on a device where it is not + available. + */ +@property(nonatomic, assign, readonly) BOOL androidInstallIfNotAvailable; + +/** @property dynamicLinkDomain + @brief The Firebase Dynamic Link domain used for out of band code flow. + */ +@property(copy, nonatomic, nullable) NSString *dynamicLinkDomain; + +/** @fn setIOSBundleID + @brief Sets the iOS bundle Id. + @param iOSBundleID The iOS bundle ID. + */ +- (void)setIOSBundleID:(NSString *)iOSBundleID; + +/** @fn setAndroidPackageName:installIfNotAvailable:minimumVersion: + @brief Sets the Android package name, the flag to indicate whether or not to install the app + and the minimum Android version supported. + @param androidPackageName The Android package name. + @param installIfNotAvailable Indicates whether or not the app should be installed if not + available. + @param minimumVersion The minimum version of Android supported. + @remarks If installIfNotAvailable is set to YES and the link is opened on an android device, it + will try to install the app if not already available. Otherwise the web URL is used. + */ +- (void)setAndroidPackageName:(NSString *)androidPackageName + installIfNotAvailable:(BOOL)installIfNotAvailable + minimumVersion:(nullable NSString *)minimumVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAdditionalUserInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAdditionalUserInfo.h new file mode 100644 index 00000000..4f6947ac --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAdditionalUserInfo.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRVerifyAssertionResponse; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAdditionalUserInfo + @brief Represents additional user data returned from an identity provider. + */ +NS_SWIFT_NAME(AdditionalUserInfo) +@interface FIRAdditionalUserInfo : NSObject + +/** @fn init + @brief This class should not be initialized manually. `FIRAdditionalUserInfo` can be retrieved + from from an instance of `FIRAuthDataResult`. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @property providerID + @brief The provider identifier. + */ +@property(nonatomic, readonly) NSString *providerID; + +/** @property profile + @brief Dictionary containing the additional IdP specific information. + */ +@property(nonatomic, readonly, nullable) NSDictionary *profile; + +/** @property username + @brief username The name of the user. + */ +@property(nonatomic, readonly, nullable) NSString *username; + +/** @property newUser + @brief Indicates whether or not the current user was signed in for the first time. + */ +@property(nonatomic, readonly, getter=isNewUser) BOOL newUser; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuth.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuth.h new file mode 100644 index 00000000..f81c8950 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuth.h @@ -0,0 +1,882 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FIRAuthErrors.h" + +#if TARGET_OS_IOS +#import "FIRAuthAPNSTokenType.h" +#endif + +@class FIRActionCodeSettings; +@class FIRApp; +@class FIRAuth; +@class FIRAuthCredential; +@class FIRAuthDataResult; +@class FIRAuthSettings; +@class FIRUser; +@protocol FIRAuthStateListener; +@protocol FIRAuthUIDelegate; +@protocol FIRFederatedAuthProvider; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRUserUpdateCallback + @brief The type of block invoked when a request to update the current user is completed. + */ +typedef void (^FIRUserUpdateCallback)(NSError *_Nullable error) NS_SWIFT_NAME(UserUpdateCallback); + +/** @typedef FIRAuthStateDidChangeListenerHandle + @brief The type of handle returned by `FIRAuth.addAuthStateDidChangeListener:`. + */ +typedef id FIRAuthStateDidChangeListenerHandle + NS_SWIFT_NAME(AuthStateDidChangeListenerHandle); + +/** @typedef FIRAuthStateDidChangeListenerBlock + @brief The type of block which can be registered as a listener for auth state did change events. + + @param auth The FIRAuth object on which state changes occurred. + @param user Optionally; the current signed in user, if any. + */ +typedef void (^FIRAuthStateDidChangeListenerBlock)(FIRAuth *auth, FIRUser *_Nullable user) + NS_SWIFT_NAME(AuthStateDidChangeListenerBlock); + +/** @typedef FIRIDTokenDidChangeListenerHandle + @brief The type of handle returned by `FIRAuth.addIDTokenDidChangeListener:`. + */ +typedef id FIRIDTokenDidChangeListenerHandle + NS_SWIFT_NAME(IDTokenDidChangeListenerHandle); + +/** @typedef FIRIDTokenDidChangeListenerBlock + @brief The type of block which can be registered as a listener for ID token did change events. + + @param auth The FIRAuth object on which ID token changes occurred. + @param user Optionally; the current signed in user, if any. + */ +typedef void (^FIRIDTokenDidChangeListenerBlock)(FIRAuth *auth, FIRUser *_Nullable user) + NS_SWIFT_NAME(IDTokenDidChangeListenerBlock); + +/** @typedef FIRAuthDataResultCallback + @brief The type of block invoked when sign-in related events complete. + + @param authResult Optionally; Result of sign-in request containing both the user and + the additional user info associated with the user. + @param error Optionally; the error which occurred - or nil if the request was successful. + */ +typedef void (^FIRAuthDataResultCallback)(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) + NS_SWIFT_NAME(AuthDataResultCallback); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + @brief The name of the `NSNotificationCenter` notification which is posted when the auth state + changes (for example, a new token has been produced, a user signs in or signs out). The + object parameter of the notification is the sender `FIRAuth` instance. + */ +extern const NSNotificationName FIRAuthStateDidChangeNotification NS_SWIFT_NAME(AuthStateDidChange); +#else +/** + @brief The name of the `NSNotificationCenter` notification which is posted when the auth state + changes (for example, a new token has been produced, a user signs in or signs out). The + object parameter of the notification is the sender `FIRAuth` instance. + */ +extern NSString *const FIRAuthStateDidChangeNotification + NS_SWIFT_NAME(AuthStateDidChangeNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** @typedef FIRAuthResultCallback + @brief The type of block invoked when sign-in related events complete. + + @param user Optionally; the signed in user, if any. + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRAuthResultCallback)(FIRUser *_Nullable user, NSError *_Nullable error) + NS_SWIFT_NAME(AuthResultCallback); + +/** @typedef FIRProviderQueryCallback + @brief The type of block invoked when a list of identity providers for a given email address is + requested. + + @param providers Optionally; a list of provider identifiers, if any. + @see FIRGoogleAuthProviderID etc. + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRProviderQueryCallback)(NSArray *_Nullable providers, + NSError *_Nullable error) + NS_SWIFT_NAME(ProviderQueryCallback); + +/** @typedef FIRSignInMethodQueryCallback + @brief The type of block invoked when a list of sign-in methods for a given email address is + requested. + */ +typedef void (^FIRSignInMethodQueryCallback)(NSArray *_Nullable, NSError *_Nullable) + NS_SWIFT_NAME(SignInMethodQueryCallback); + +/** @typedef FIRSendPasswordResetCallback + @brief The type of block invoked when sending a password reset email. + + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRSendPasswordResetCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(SendPasswordResetCallback); + +/** @typedef FIRSendSignInLinkToEmailCallback + @brief The type of block invoked when sending an email sign-in link email. + */ +typedef void (^FIRSendSignInLinkToEmailCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(SendSignInLinkToEmailCallback); + +/** @typedef FIRConfirmPasswordResetCallback + @brief The type of block invoked when performing a password reset. + + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRConfirmPasswordResetCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(ConfirmPasswordResetCallback); + +/** @typedef FIRVerifyPasswordResetCodeCallback + @brief The type of block invoked when verifying that an out of band code should be used to + perform password reset. + + @param email Optionally; the email address of the user for which the out of band code applies. + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRVerifyPasswordResetCodeCallback)(NSString *_Nullable email, + NSError *_Nullable error) + NS_SWIFT_NAME(VerifyPasswordResetCodeCallback); + +/** @typedef FIRApplyActionCodeCallback + @brief The type of block invoked when applying an action code. + + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRApplyActionCodeCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(ApplyActionCodeCallback); + +typedef void (^FIRAuthVoidErrorCallback)(NSError *_Nullable) NS_SWIFT_NAME(AuthVoidErrorCallback); + +/** + @brief Deprecated. Please directly use email or previousEmail properties instead. + */ +typedef NS_ENUM(NSInteger, FIRActionDataKey) { + /** Deprecated. Please directly use email property instead. */ + FIRActionCodeEmailKey = 0, + + /** Deprecated. Please directly use previousEmail property instead. */ + FIRActionCodeFromEmailKey = 1, + +} NS_SWIFT_NAME(ActionDataKey) + DEPRECATED_MSG_ATTRIBUTE("Please directly use email or previousEmail properties instead."); + +/** @class FIRActionCodeInfo + @brief Manages information regarding action codes. + */ +NS_SWIFT_NAME(ActionCodeInfo) +@interface FIRActionCodeInfo : NSObject + +/** + @brief Operations which can be performed with action codes. + */ +typedef NS_ENUM(NSInteger, FIRActionCodeOperation) { + /** Action code for unknown operation. */ + FIRActionCodeOperationUnknown = 0, + + /** Action code for password reset operation. */ + FIRActionCodeOperationPasswordReset = 1, + + /** Action code for verify email operation. */ + FIRActionCodeOperationVerifyEmail = 2, + + /** Action code for recover email operation. */ + FIRActionCodeOperationRecoverEmail = 3, + + /** Action code for email link operation. */ + FIRActionCodeOperationEmailLink = 4, + + /** Action code for verifing and changing email */ + FIRActionCodeOperationVerifyAndChangeEmail = 5, + + /** Action code for reverting second factor addition */ + FIRActionCodeOperationRevertSecondFactorAddition = 6, + +} NS_SWIFT_NAME(ActionCodeOperation); + +/** + @brief The operation being performed. + */ +@property(nonatomic, readonly) FIRActionCodeOperation operation; + +/** @fn dataForKey: + @brief Deprecated. Please directly use email or previousEmail properties instead. + */ +- (NSString *)dataForKey:(FIRActionDataKey)key + DEPRECATED_MSG_ATTRIBUTE("Please directly use email or previousEmail properties instead."); + +/** @property email + @brief The email address to which the code was sent. The new email address in the case of + FIRActionCodeOperationRecoverEmail. + */ +@property(nonatomic, nullable, readonly, copy) NSString *email; + +/** @property previousEmail + @brief The email that is being recovered in the case of FIRActionCodeOperationRecoverEmail. + */ +@property(nonatomic, nullable, readonly, copy) NSString *previousEmail; + +/** @fn init + @brief please use initWithOperation: instead. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +/** @class FIRActionCodeURL + @brief This class will allow developers to easily extract information about out of band links. + */ +NS_SWIFT_NAME(ActionCodeURL) +@interface FIRActionCodeURL : NSObject + +/** @property APIKey + @brief Returns the API key from the link. nil, if not provided. + */ +@property(nonatomic, nullable, copy, readonly) NSString *APIKey; + +/** @property operation + @brief Returns the mode of oob action. The property will be of FIRActionCodeOperation type. + It will return FIRActionCodeOperationUnknown if no oob action is provided. + */ +@property(nonatomic, readonly) FIRActionCodeOperation operation; + +/** @property code + @brief Returns the email action code from the link. nil, if not provided. + */ +@property(nonatomic, nullable, copy, readonly) NSString *code; + +/** @property continueURL + @brief Returns the continue URL from the link. nil, if not provided. + */ +@property(nonatomic, nullable, copy, readonly) NSURL *continueURL; + +/** @property languageCode + @brief Returns the language code from the link. nil, if not provided. + */ +@property(nonatomic, nullable, copy, readonly) NSString *languageCode; + +/** @fn actionCodeURLWithLink: + @brief Construct an FIRActionCodeURL from an out of band link (e.g. email link). + @param link The oob link string used to construct the action code URL. + @return The FIRActionCodeURL object constructed based on the oob link provided. + */ ++ (nullable instancetype)actionCodeURLWithLink:(NSString *)link; + +/** @fn init + @brief Please use actionCodeURLWithLink: for Objective-C or actionCodeURLWithLink(link:) for + Swift instead. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +/** @typedef FIRCheckActionCodeCallBack + @brief The type of block invoked when performing a check action code operation. + + @param info Metadata corresponding to the action code. + @param error Optionally; if an error occurs, this is the NSError object that describes the + problem. Set to nil otherwise. + */ +typedef void (^FIRCheckActionCodeCallBack)(FIRActionCodeInfo *_Nullable info, + NSError *_Nullable error) + NS_SWIFT_NAME(CheckActionCodeCallback); + +/** @class FIRAuth + @brief Manages authentication for Firebase apps. + @remarks This class is thread-safe. + */ +NS_SWIFT_NAME(Auth) +@interface FIRAuth : NSObject + +/** @fn auth + @brief Gets the auth object for the default Firebase app. + @remarks The default Firebase app must have already been configured or an exception will be + raised. + */ ++ (FIRAuth *)auth NS_SWIFT_NAME(auth()); + +/** @fn authWithApp: + @brief Gets the auth object for a `FIRApp`. + + @param app The FIRApp for which to retrieve the associated FIRAuth instance. + @return The FIRAuth instance associated with the given FIRApp. + */ ++ (FIRAuth *)authWithApp:(FIRApp *)app NS_SWIFT_NAME(auth(app:)); + +/** @property app + @brief Gets the `FIRApp` object that this auth object is connected to. + */ +@property(nonatomic, weak, readonly, nullable) FIRApp *app; + +/** @property currentUser + @brief Synchronously gets the cached current user, or null if there is none. + */ +@property(nonatomic, strong, readonly, nullable) FIRUser *currentUser; + +/** @property languageCode + @brief The current user language code. This property can be set to the app's current language by + calling `useAppLanguage`. + + @remarks The string used to set this property must be a language code that follows BCP 47. + */ +@property(nonatomic, copy, nullable) NSString *languageCode; + +/** @property settings + @brief Contains settings related to the auth object. + */ +@property(nonatomic, copy, nullable) FIRAuthSettings *settings; + +/** @property userAccessGroup + @brief The current user access group that the Auth instance is using. Default is nil. + */ +@property(readonly, nonatomic, copy, nullable) NSString *userAccessGroup; + +#if TARGET_OS_IOS +/** @property APNSToken + @brief The APNs token used for phone number authentication. The type of the token (production + or sandbox) will be attempted to be automatcially detected. + @remarks If swizzling is disabled, the APNs Token must be set for phone number auth to work, + by either setting this property or by calling `setAPNSToken:type:` + */ +@property(nonatomic, strong, nullable) NSData *APNSToken; +#endif + +/** @fn init + @brief Please access auth instances using `FIRAuth.auth` and `FIRAuth.authForApp:`. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn updateCurrentUser:completion: + @brief Sets the currentUser on the calling Auth instance to the provided user object. + @param user The user object to be set as the current user of the calling Auth instance. + @param completion Optionally; a block invoked after the user of the calling Auth instance has + been updated or an error was encountered. + */ +- (void)updateCurrentUser:(FIRUser *)user completion:(nullable FIRUserUpdateCallback)completion; + +/** @fn fetchProvidersForEmail:completion: + @brief Please use fetchSignInMethodsForEmail:completion: for Objective-C or + fetchSignInMethods(forEmail:completion:) for Swift instead. + */ +- (void)fetchProvidersForEmail:(NSString *)email + completion:(nullable FIRProviderQueryCallback)completion + DEPRECATED_MSG_ATTRIBUTE("Please use fetchSignInMethodsForEmail:completion: for Objective-C or " + "fetchSignInMethods(forEmail:completion:) for Swift instead."); + +/** @fn fetchSignInMethodsForEmail:completion: + @brief Fetches the list of all sign-in methods previously used for the provided email address. + + @param email The email address for which to obtain a list of sign-in methods. + @param completion Optionally; a block which is invoked when the list of sign in methods for the + specified email address is ready or an error was encountered. Invoked asynchronously on the + main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + @remarks See @c FIRAuthErrors for a list of error codes that are common to all API methods. + */ + +- (void)fetchSignInMethodsForEmail:(NSString *)email + completion:(nullable FIRSignInMethodQueryCallback)completion; + +/** @fn signInWithEmail:password:completion: + @brief Signs in using an email address and password. + + @param email The user's email address. + @param password The user's password. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and password + accounts are not enabled. Enable them in the Auth section of the + Firebase console. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted + sign in with an incorrect password. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)signInWithEmail:(NSString *)email + password:(NSString *)password + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn signInWithEmail:link:completion: + @brief Signs in using an email address and email sign-in link. + + @param email The user's email address. + @param link The email sign-in link. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and email sign-in link + accounts are not enabled. Enable them in the Auth section of the + Firebase console. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is invalid. + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + +- (void)signInWithEmail:(NSString *)email + link:(NSString *)link + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn signInWithProvider:UIDelegate:completion: + @brief Signs in using the provided auth provider instance. + + @param provider An instance of an auth provider used to initiate the sign-in flow. + @param UIDelegate Optionally an instance of a class conforming to the FIRAuthUIDelegate + protocol, this is used for presenting the web context. If nil, a default FIRAuthUIDelegate + will be used. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: +
    +
  • @c FIRAuthErrorCodeOperationNotAllowed - Indicates that email and password + accounts are not enabled. Enable them in the Auth section of the + Firebase console. +
  • +
  • @c FIRAuthErrorCodeUserDisabled - Indicates the user's account is disabled. +
  • +
  • @c FIRAuthErrorCodeWebNetworkRequestFailed - Indicates that a network request within a + SFSafariViewController or WKWebView failed. +
  • +
  • @c FIRAuthErrorCodeWebInternalError - Indicates that an internal error occurred within a + SFSafariViewController or WKWebView. +
  • +
  • @c FIRAuthErrorCodeWebSignInUserInteractionFailure - Indicates a general failure during + a web sign-in flow. +
  • +
  • @c FIRAuthErrorCodeWebContextAlreadyPresented - Indicates that an attempt was made to + present a new web context while one was already being presented. +
  • +
  • @c FIRAuthErrorCodeWebContextCancelled - Indicates that the URL presentation was + cancelled prematurely by the user. +
  • +
  • @c FIRAuthErrorCodeAccountExistsWithDifferentCredential - Indicates the email asserted + by the credential (e.g. the email in a Facebook access token) is already in use by an + existing account, that cannot be authenticated with this sign-in method. Call + fetchProvidersForEmail for this user’s email and then prompt them to sign in with any of + the sign-in providers returned. This error will only be thrown if the "One account per + email address" setting is enabled in the Firebase console, under Auth settings. +
  • +
+ + @remarks See @c FIRAuthErrors for a list of error codes that are common to all API methods. + */ +- (void)signInWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn signInAndRetrieveDataWithCredential:completion: + @brief Please use signInWithCredential:completion: for Objective-C or " + "signIn(with:completion:) for Swift instead. + */ +- (void)signInAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion + DEPRECATED_MSG_ATTRIBUTE("Please use signInWithCredential:completion: for Objective-C or " + "signIn(with:completion:) for Swift instead."); + +/** @fn signInWithCredential:completion: + @brief Asynchronously signs in to Firebase with the given 3rd-party credentials (e.g. a Facebook + login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional + identity provider data. + + @param credential The credential supplied by the IdP. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidCredential` - Indicates the supplied credential is invalid. + This could happen if it has expired or it is malformed. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts + with the identity provider represented by the credential are not enabled. + Enable them in the Auth section of the Firebase console. + + `FIRAuthErrorCodeAccountExistsWithDifferentCredential` - Indicates the email asserted + by the credential (e.g. the email in a Facebook access token) is already in use by an + existing account, that cannot be authenticated with this sign-in method. Call + fetchProvidersForEmail for this user’s email and then prompt them to sign in with any of + the sign-in providers returned. This error will only be thrown if the "One account per + email address" setting is enabled in the Firebase console, under Auth settings. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted sign in with an + incorrect password, if credential is of the type EmailPasswordAuthCredential. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + `FIRAuthErrorCodeMissingVerificationID` - Indicates that the phone auth credential was + created with an empty verification ID. + + `FIRAuthErrorCodeMissingVerificationCode` - Indicates that the phone auth credential + was created with an empty verification code. + + `FIRAuthErrorCodeInvalidVerificationCode` - Indicates that the phone auth credential + was created with an invalid verification Code. + + `FIRAuthErrorCodeInvalidVerificationID` - Indicates that the phone auth credential was + created with an invalid verification ID. + + `FIRAuthErrorCodeSessionExpired` - Indicates that the SMS code has expired. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods +*/ +- (void)signInWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn signInAnonymouslyWithCompletion: + @brief Asynchronously creates and becomes an anonymous user. + @param completion Optionally; a block which is invoked when the sign in finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks If there is already an anonymous user signed in, that user will be returned instead. + If there is any other existing user signed in, that user will be signed out. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that anonymous accounts are + not enabled. Enable them in the Auth section of the Firebase console. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)signInAnonymouslyWithCompletion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn signInWithCustomToken:completion: + @brief Asynchronously signs in to Firebase with the given Auth token. + + @param token A self-signed custom auth token. + @param completion Optionally; a block which is invoked when the sign in finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidCustomToken` - Indicates a validation error with + the custom token. + + `FIRAuthErrorCodeCustomTokenMismatch` - Indicates the service account and the API key + belong to different projects. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)signInWithCustomToken:(NSString *)token + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn createUserWithEmail:password:completion: + @brief Creates and, on success, signs in a user with the given email address and password. + + @param email The user's email address. + @param password The user's desired password. + @param completion Optionally; a block which is invoked when the sign up flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + `FIRAuthErrorCodeEmailAlreadyInUse` - Indicates the email used to attempt sign up + already exists. Call fetchProvidersForEmail to check which sign-in mechanisms the user + used, and prompt the user to sign in with one of those. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and password accounts + are not enabled. Enable them in the Auth section of the Firebase console. + + `FIRAuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is + considered too weak. The NSLocalizedFailureReasonErrorKey field in the NSError.userInfo + dictionary object will contain more detailed explanation that can be shown to the user. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)createUserWithEmail:(NSString *)email + password:(NSString *)password + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn confirmPasswordResetWithCode:newPassword:completion: + @brief Resets the password given a code sent to the user outside of the app and a new password + for the user. + + @param newPassword The new password. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is + considered too weak. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates the administrator disabled sign + in with the specified identity provider. + + `FIRAuthErrorCodeExpiredActionCode` - Indicates the OOB code is expired. + + `FIRAuthErrorCodeInvalidActionCode` - Indicates the OOB code is invalid. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)confirmPasswordResetWithCode:(NSString *)code + newPassword:(NSString *)newPassword + completion:(FIRConfirmPasswordResetCallback)completion; + +/** @fn checkActionCode:completion: + @brief Checks the validity of an out of band code. + + @param code The out of band code to check validity. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ +- (void)checkActionCode:(NSString *)code completion:(FIRCheckActionCodeCallBack)completion; + +/** @fn verifyPasswordResetCode:completion: + @brief Checks the validity of a verify password reset code. + + @param code The password reset code to be verified. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ +- (void)verifyPasswordResetCode:(NSString *)code + completion:(FIRVerifyPasswordResetCodeCallback)completion; + +/** @fn applyActionCode:completion: + @brief Applies out of band code. + + @param code The out of band code to be applied. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks This method will not work for out of band codes which require an additional parameter, + such as password reset code. + */ +- (void)applyActionCode:(NSString *)code completion:(FIRApplyActionCodeCallback)completion; + +/** @fn sendPasswordResetWithEmail:completion: + @brief Initiates a password reset for the given email address. + + @param email The email address of the user. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + + */ +- (void)sendPasswordResetWithEmail:(NSString *)email + completion:(nullable FIRSendPasswordResetCallback)completion; + +/** @fn sendPasswordResetWithEmail:actionCodeSetting:completion: + @brief Initiates a password reset for the given email address and @FIRActionCodeSettings object. + + @param email The email address of the user. + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + `FIRAuthErrorCodeMissingIosBundleID` - Indicates that the iOS bundle ID is missing when + `handleCodeInApp` is set to YES. + + `FIRAuthErrorCodeMissingAndroidPackageName` - Indicates that the android package name + is missing when the `androidInstallApp` flag is set to true. + + `FIRAuthErrorCodeUnauthorizedDomain` - Indicates that the domain specified in the + continue URL is not whitelisted in the Firebase console. + + `FIRAuthErrorCodeInvalidContinueURI` - Indicates that the domain specified in the + continue URI is not valid. + + + */ +- (void)sendPasswordResetWithEmail:(NSString *)email + actionCodeSettings:(FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRSendPasswordResetCallback)completion; + +/** @fn sendSignInLinkToEmail:actionCodeSettings:completion: + @brief Sends a sign in with email link to provided email address. + + @param email The email address of the user. + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ +- (void)sendSignInLinkToEmail:(NSString *)email + actionCodeSettings:(FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRSendSignInLinkToEmailCallback)completion; + +/** @fn signOut: + @brief Signs out the current user. + + @param error Optionally; if an error occurs, upon return contains an NSError object that + describes the problem; is nil otherwise. + @return @YES when the sign out request was successful. @NO otherwise. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeKeychainError` - Indicates an error occurred when accessing the + keychain. The `NSLocalizedFailureReasonErrorKey` field in the `NSError.userInfo` + dictionary will contain more information about the error encountered. + + + + */ +- (BOOL)signOut:(NSError *_Nullable *_Nullable)error; + +/** @fn isSignInWithEmailLink + @brief Checks if link is an email sign-in link. + + @param link The email sign-in link. + @return @YES when the link passed matches the expected format of an email sign-in link. + */ +- (BOOL)isSignInWithEmailLink:(NSString *)link; + +/** @fn addAuthStateDidChangeListener: + @brief Registers a block as an "auth state did change" listener. To be invoked when: + + + The block is registered as a listener, + + A user with a different UID from the current user has signed in, or + + The current user has signed out. + + @param listener The block to be invoked. The block is always invoked asynchronously on the main + thread, even for it's initial invocation after having been added as a listener. + + @remarks The block is invoked immediately after adding it according to it's standard invocation + semantics, asynchronously on the main thread. Users should pay special attention to + making sure the block does not inadvertently retain objects which should not be retained by + the long-lived block. The block itself will be retained by `FIRAuth` until it is + unregistered or until the `FIRAuth` instance is otherwise deallocated. + + @return A handle useful for manually unregistering the block as a listener. + */ +- (FIRAuthStateDidChangeListenerHandle)addAuthStateDidChangeListener: + (FIRAuthStateDidChangeListenerBlock)listener; + +/** @fn removeAuthStateDidChangeListener: + @brief Unregisters a block as an "auth state did change" listener. + + @param listenerHandle The handle for the listener. + */ +- (void)removeAuthStateDidChangeListener:(FIRAuthStateDidChangeListenerHandle)listenerHandle; + +/** @fn addIDTokenDidChangeListener: + @brief Registers a block as an "ID token did change" listener. To be invoked when: + + + The block is registered as a listener, + + A user with a different UID from the current user has signed in, + + The ID token of the current user has been refreshed, or + + The current user has signed out. + + @param listener The block to be invoked. The block is always invoked asynchronously on the main + thread, even for it's initial invocation after having been added as a listener. + + @remarks The block is invoked immediately after adding it according to it's standard invocation + semantics, asynchronously on the main thread. Users should pay special attention to + making sure the block does not inadvertently retain objects which should not be retained by + the long-lived block. The block itself will be retained by `FIRAuth` until it is + unregistered or until the `FIRAuth` instance is otherwise deallocated. + + @return A handle useful for manually unregistering the block as a listener. + */ +- (FIRIDTokenDidChangeListenerHandle)addIDTokenDidChangeListener: + (FIRIDTokenDidChangeListenerBlock)listener; + +/** @fn removeIDTokenDidChangeListener: + @brief Unregisters a block as an "ID token did change" listener. + + @param listenerHandle The handle for the listener. + */ +- (void)removeIDTokenDidChangeListener:(FIRIDTokenDidChangeListenerHandle)listenerHandle; + +/** @fn useAppLanguage + @brief Sets `languageCode` to the app's current language. + */ +- (void)useAppLanguage; + +#if TARGET_OS_IOS + +/** @fn canHandleURL: + @brief Whether the specific URL is handled by `FIRAuth` . + @param URL The URL received by the application delegate from any of the openURL method. + @return Whether or the URL is handled. YES means the URL is for Firebase Auth + so the caller should ignore the URL from further processing, and NO means the + the URL is for the app (or another libaray) so the caller should continue handling + this URL as usual. + @remarks If swizzling is disabled, URLs received by the application delegate must be forwarded + to this method for phone number auth to work. + */ +- (BOOL)canHandleURL:(nonnull NSURL *)URL; + +/** @fn setAPNSToken:type: + @brief Sets the APNs token along with its type. + @remarks If swizzling is disabled, the APNs Token must be set for phone number auth to work, + by either setting calling this method or by setting the `APNSToken` property. + */ +- (void)setAPNSToken:(NSData *)token type:(FIRAuthAPNSTokenType)type; + +/** @fn canHandleNotification: + @brief Whether the specific remote notification is handled by `FIRAuth` . + @param userInfo A dictionary that contains information related to the + notification in question. + @return Whether or the notification is handled. YES means the notification is for Firebase Auth + so the caller should ignore the notification from further processing, and NO means the + the notification is for the app (or another libaray) so the caller should continue handling + this notification as usual. + @remarks If swizzling is disabled, related remote notifications must be forwarded to this method + for phone number auth to work. + */ +- (BOOL)canHandleNotification:(NSDictionary *)userInfo; + +#endif // TARGET_OS_IOS + +#pragma mark - User sharing + +/** @fn useUserAccessGroup:error: + @brief Switch userAccessGroup and current user to the given accessGroup and the user stored in + it. + */ +- (BOOL)useUserAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn getStoredUserForAccessGroup:error: + @brief Get the stored user in the given accessGroup. + */ +- (nullable FIRUser *)getStoredUserForAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthAPNSTokenType.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthAPNSTokenType.h new file mode 100644 index 00000000..5630e219 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthAPNSTokenType.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * @brief The APNs token type for the app. + */ +typedef NS_ENUM(NSInteger, FIRAuthAPNSTokenType) { + + /** Unknown token type. + The actual token type will be detected from the provisioning profile in the app's bundle. + */ + FIRAuthAPNSTokenTypeUnknown, + + /** Sandbox token type. + */ + FIRAuthAPNSTokenTypeSandbox, + + /** Production token type. + */ + FIRAuthAPNSTokenTypeProd, +} NS_SWIFT_NAME(AuthAPNSTokenType); + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthCredential.h new file mode 100644 index 00000000..106d844f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthCredential.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthCredential + @brief Represents a credential. + */ +NS_SWIFT_NAME(AuthCredential) +@interface FIRAuthCredential : NSObject + +/** @property provider + @brief Gets the name of the identity provider for the credential. + */ +@property(nonatomic, copy, readonly) NSString *provider; + +/** @fn init + @brief This is an abstract base class. Concrete instances should be created via factory + methods available in the various authentication provider libraries (like the Facebook + provider or the Google provider libraries.) + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthDataResult.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthDataResult.h new file mode 100644 index 00000000..93c8b3bc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthDataResult.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAdditionalUserInfo; +@class FIRAuthCredential; +@class FIRUser; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthDataResult + @brief Helper object that contains the result of a successful sign-in, link and reauthenticate + action. It contains references to a FIRUser instance and a FIRAdditionalUserInfo instance. + */ +NS_SWIFT_NAME(AuthDataResult) +@interface FIRAuthDataResult : NSObject + +/** @fn init + @brief This class should not be initialized manually. `FIRAuthDataResult` instance is + returned as part of `FIRAuthDataResultCallback`. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @property user + @brief The signed in user. + */ +@property(nonatomic, readonly) FIRUser *user; + +/** @property additionalUserInfo + @brief If available contains the additional IdP specific information about signed in user. + */ +@property(nonatomic, readonly, nullable) FIRAdditionalUserInfo *additionalUserInfo; + +/** @property credential + @brief This property will be non-nil after a successful headful-lite sign-in via + signInWithProvider:UIDelegate:. May be used to obtain the accessToken and/or IDToken + pertaining to a recently signed-in user. + */ +@property(nonatomic, readonly, nullable) FIRAuthCredential *credential; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthErrors.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthErrors.h new file mode 100644 index 00000000..dede5a07 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthErrors.h @@ -0,0 +1,421 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthErrors + @remarks Error Codes common to all API Methods: + + + `FIRAuthErrorCodeNetworkError` + + `FIRAuthErrorCodeUserNotFound` + + `FIRAuthErrorCodeUserTokenExpired` + + `FIRAuthErrorCodeTooManyRequests` + + `FIRAuthErrorCodeInvalidAPIKey` + + `FIRAuthErrorCodeAppNotAuthorized` + + `FIRAuthErrorCodeKeychainError` + + `FIRAuthErrorCodeInternalError` + + @remarks Common error codes for `FIRUser` operations: + + + `FIRAuthErrorCodeInvalidUserToken` + + `FIRAuthErrorCodeUserDisabled` + + */ +NS_SWIFT_NAME(AuthErrors) +@interface FIRAuthErrors + +/** + @brief The Firebase Auth error domain. + */ +extern NSString *const FIRAuthErrorDomain NS_SWIFT_NAME(AuthErrorDomain); + +/** + @brief The name of the key for the error short string of an error code. + */ +extern NSString *const FIRAuthErrorUserInfoNameKey NS_SWIFT_NAME(AuthErrorUserInfoNameKey); + +/** + @brief Errors with one of the following three codes: + - `FIRAuthErrorCodeAccountExistsWithDifferentCredential` + - `FIRAuthErrorCodeCredentialAlreadyInUse` + - `FIRAuthErrorCodeEmailAlreadyInUse` + may contain an `NSError.userInfo` dictinary object which contains this key. The value + associated with this key is an NSString of the email address of the account that already + exists. + */ +extern NSString *const FIRAuthErrorUserInfoEmailKey NS_SWIFT_NAME(AuthErrorUserInfoEmailKey); + +/** + @brief The key used to read the updated Auth credential from the userInfo dictionary of the + NSError object returned. This is the updated auth credential the developer should use for + recovery if applicable. + */ +extern NSString *const FIRAuthErrorUserInfoUpdatedCredentialKey + NS_SWIFT_NAME(AuthErrorUserInfoUpdatedCredentialKey); + +/** + @brief The key used to read the MFA resolver from the userInfo dictionary of the NSError object + returned when 2FA is required for sign-incompletion. + */ +extern NSString *const FIRAuthErrorUserInfoMultiFactorResolverKey + NS_SWIFT_NAME(AuthErrorUserInfoMultiFactorResolverKey); + +/** + @brief Error codes used by Firebase Auth. + */ +typedef NS_ENUM(NSInteger, FIRAuthErrorCode) { + /** Indicates a validation error with the custom token. + */ + FIRAuthErrorCodeInvalidCustomToken = 17000, + + /** Indicates the service account and the API key belong to different projects. + */ + FIRAuthErrorCodeCustomTokenMismatch = 17002, + + /** Indicates the IDP token or requestUri is invalid. + */ + FIRAuthErrorCodeInvalidCredential = 17004, + + /** Indicates the user's account is disabled on the server. + */ + FIRAuthErrorCodeUserDisabled = 17005, + + /** Indicates the administrator disabled sign in with the specified identity provider. + */ + FIRAuthErrorCodeOperationNotAllowed = 17006, + + /** Indicates the email used to attempt a sign up is already in use. + */ + FIRAuthErrorCodeEmailAlreadyInUse = 17007, + + /** Indicates the email is invalid. + */ + FIRAuthErrorCodeInvalidEmail = 17008, + + /** Indicates the user attempted sign in with a wrong password. + */ + FIRAuthErrorCodeWrongPassword = 17009, + + /** Indicates that too many requests were made to a server method. + */ + FIRAuthErrorCodeTooManyRequests = 17010, + + /** Indicates the user account was not found. + */ + FIRAuthErrorCodeUserNotFound = 17011, + + /** Indicates account linking is required. + */ + FIRAuthErrorCodeAccountExistsWithDifferentCredential = 17012, + + /** Indicates the user has attemped to change email or password more than 5 minutes after + signing in. + */ + FIRAuthErrorCodeRequiresRecentLogin = 17014, + + /** Indicates an attempt to link a provider to which the account is already linked. + */ + FIRAuthErrorCodeProviderAlreadyLinked = 17015, + + /** Indicates an attempt to unlink a provider that is not linked. + */ + FIRAuthErrorCodeNoSuchProvider = 17016, + + /** Indicates user's saved auth credential is invalid, the user needs to sign in again. + */ + FIRAuthErrorCodeInvalidUserToken = 17017, + + /** Indicates a network error occurred (such as a timeout, interrupted connection, or + unreachable host). These types of errors are often recoverable with a retry. The + `NSUnderlyingError` field in the `NSError.userInfo` dictionary will contain the error + encountered. + */ + FIRAuthErrorCodeNetworkError = 17020, + + /** Indicates the saved token has expired, for example, the user may have changed account + password on another device. The user needs to sign in again on the device that made this + request. + */ + FIRAuthErrorCodeUserTokenExpired = 17021, + + /** Indicates an invalid API key was supplied in the request. + */ + FIRAuthErrorCodeInvalidAPIKey = 17023, + + /** Indicates that an attempt was made to reauthenticate with a user which is not the current + user. + */ + FIRAuthErrorCodeUserMismatch = 17024, + + /** Indicates an attempt to link with a credential that has already been linked with a + different Firebase account + */ + FIRAuthErrorCodeCredentialAlreadyInUse = 17025, + + /** Indicates an attempt to set a password that is considered too weak. + */ + FIRAuthErrorCodeWeakPassword = 17026, + + /** Indicates the App is not authorized to use Firebase Authentication with the + provided API Key. + */ + FIRAuthErrorCodeAppNotAuthorized = 17028, + + /** Indicates the OOB code is expired. + */ + FIRAuthErrorCodeExpiredActionCode = 17029, + + /** Indicates the OOB code is invalid. + */ + FIRAuthErrorCodeInvalidActionCode = 17030, + + /** Indicates that there are invalid parameters in the payload during a "send password reset + * email" attempt. + */ + FIRAuthErrorCodeInvalidMessagePayload = 17031, + + /** Indicates that the sender email is invalid during a "send password reset email" attempt. + */ + FIRAuthErrorCodeInvalidSender = 17032, + + /** Indicates that the recipient email is invalid. + */ + FIRAuthErrorCodeInvalidRecipientEmail = 17033, + + /** Indicates that an email address was expected but one was not provided. + */ + FIRAuthErrorCodeMissingEmail = 17034, + + // The enum values 17035 is reserved and should NOT be used for new error codes. + + /** Indicates that the iOS bundle ID is missing when a iOS App Store ID is provided. + */ + FIRAuthErrorCodeMissingIosBundleID = 17036, + + /** Indicates that the android package name is missing when the `androidInstallApp` flag is set + to true. + */ + FIRAuthErrorCodeMissingAndroidPackageName = 17037, + + /** Indicates that the domain specified in the continue URL is not whitelisted in the Firebase + console. + */ + FIRAuthErrorCodeUnauthorizedDomain = 17038, + + /** Indicates that the domain specified in the continue URI is not valid. + */ + FIRAuthErrorCodeInvalidContinueURI = 17039, + + /** Indicates that a continue URI was not provided in a request to the backend which requires + one. + */ + FIRAuthErrorCodeMissingContinueURI = 17040, + + /** Indicates that a phone number was not provided in a call to + `verifyPhoneNumber:completion:`. + */ + FIRAuthErrorCodeMissingPhoneNumber = 17041, + + /** Indicates that an invalid phone number was provided in a call to + `verifyPhoneNumber:completion:`. + */ + FIRAuthErrorCodeInvalidPhoneNumber = 17042, + + /** Indicates that the phone auth credential was created with an empty verification code. + */ + FIRAuthErrorCodeMissingVerificationCode = 17043, + + /** Indicates that an invalid verification code was used in the verifyPhoneNumber request. + */ + FIRAuthErrorCodeInvalidVerificationCode = 17044, + + /** Indicates that the phone auth credential was created with an empty verification ID. + */ + FIRAuthErrorCodeMissingVerificationID = 17045, + + /** Indicates that an invalid verification ID was used in the verifyPhoneNumber request. + */ + FIRAuthErrorCodeInvalidVerificationID = 17046, + + /** Indicates that the APNS device token is missing in the verifyClient request. + */ + FIRAuthErrorCodeMissingAppCredential = 17047, + + /** Indicates that an invalid APNS device token was used in the verifyClient request. + */ + FIRAuthErrorCodeInvalidAppCredential = 17048, + + // The enum values between 17048 and 17051 are reserved and should NOT be used for new error + // codes. + + /** Indicates that the SMS code has expired. + */ + FIRAuthErrorCodeSessionExpired = 17051, + + /** Indicates that the quota of SMS messages for a given project has been exceeded. + */ + FIRAuthErrorCodeQuotaExceeded = 17052, + + /** Indicates that the APNs device token could not be obtained. The app may not have set up + remote notification correctly, or may fail to forward the APNs device token to FIRAuth + if app delegate swizzling is disabled. + */ + FIRAuthErrorCodeMissingAppToken = 17053, + + /** Indicates that the app fails to forward remote notification to FIRAuth. + */ + FIRAuthErrorCodeNotificationNotForwarded = 17054, + + /** Indicates that the app could not be verified by Firebase during phone number authentication. + */ + FIRAuthErrorCodeAppNotVerified = 17055, + + /** Indicates that the reCAPTCHA token is not valid. + */ + FIRAuthErrorCodeCaptchaCheckFailed = 17056, + + /** Indicates that an attempt was made to present a new web context while one was already being + presented. + */ + FIRAuthErrorCodeWebContextAlreadyPresented = 17057, + + /** Indicates that the URL presentation was cancelled prematurely by the user. + */ + FIRAuthErrorCodeWebContextCancelled = 17058, + + /** Indicates a general failure during the app verification flow. + */ + FIRAuthErrorCodeAppVerificationUserInteractionFailure = 17059, + + /** Indicates that the clientID used to invoke a web flow is invalid. + */ + FIRAuthErrorCodeInvalidClientID = 17060, + + /** Indicates that a network request within a SFSafariViewController or WKWebView failed. + */ + FIRAuthErrorCodeWebNetworkRequestFailed = 17061, + + /** Indicates that an internal error occurred within a SFSafariViewController or WKWebView. + */ + FIRAuthErrorCodeWebInternalError = 17062, + + /** Indicates a general failure during a web sign-in flow. + */ + FIRAuthErrorCodeWebSignInUserInteractionFailure = 17063, + + /** Indicates that the local player was not authenticated prior to attempting Game Center + signin. + */ + FIRAuthErrorCodeLocalPlayerNotAuthenticated = 17066, + + /** Indicates that a non-null user was expected as an argmument to the operation but a null + user was provided. + */ + FIRAuthErrorCodeNullUser = 17067, + + /** Indicates that a Firebase Dynamic Link is not activated. + */ + FIRAuthErrorCodeDynamicLinkNotActivated = 17068, + + /** + * Represents the error code for when the given provider id for a web operation is invalid. + */ + FIRAuthErrorCodeInvalidProviderID = 17071, + + /** Indicates that the Firebase Dynamic Link domain used is either not configured or is + unauthorized for the current project. + */ + FIRAuthErrorCodeInvalidDynamicLinkDomain = 17074, + + /** Indicates that the credential is rejected because it's misformed or mismatching. + */ + FIRAuthErrorCodeRejectedCredential = 17075, + + /** Indicates that the GameKit framework is not linked prior to attempting Game Center signin. + */ + FIRAuthErrorCodeGameKitNotLinked = 17076, + + /** Indicates that the second factor is required for signin. + */ + FIRAuthErrorCodeSecondFactorRequired = 17078, + + /** Indicates that the multi factor session is missing. + */ + FIRAuthErrorCodeMissingMultiFactorSession = 17081, + + /** Indicates that the multi factor info is missing. + */ + FIRAuthErrorCodeMissingMultiFactorInfo = 17082, + + /** Indicates that the multi factor session is invalid. + */ + FIRAuthErrorCodeInvalidMultiFactorSession = 17083, + + /** Indicates that the multi factor info is not found. + */ + FIRAuthErrorCodeMultiFactorInfoNotFound = 17084, + + /** Indicates that the operation is admin restricted. + */ + FIRAuthErrorCodeAdminRestrictedOperation = 17085, + + /** Indicates that the email is required for verification. + */ + FIRAuthErrorCodeUnverifiedEmail = 17086, + + /** Indicates that the second factor is already enrolled. + */ + FIRAuthErrorCodeSecondFactorAlreadyEnrolled = 17087, + + /** Indicates that the maximum second factor count is exceeded. + */ + FIRAuthErrorCodeMaximumSecondFactorCountExceeded = 17088, + + /** Indicates that the first factor is not supported. + */ + FIRAuthErrorCodeUnsupportedFirstFactor = 17089, + + /** Indicates that the a verifed email is required to changed to. + */ + FIRAuthErrorCodeEmailChangeNeedsVerification = 17090, + + /** Indicates that the nonce is missing or invalid. + */ + FIRAuthErrorCodeMissingOrInvalidNonce = 17094, + + /** Indicates an error for when the client identifier is missing. + */ + FIRAuthErrorCodeMissingClientIdentifier = 17993, + + /** Indicates an error occurred while attempting to access the keychain. + */ + FIRAuthErrorCodeKeychainError = 17995, + + /** Indicates an internal error occurred. + */ + FIRAuthErrorCodeInternalError = 17999, + + /** Raised when a JWT fails to parse correctly. May be accompanied by an underlying error + describing which step of the JWT parsing process failed. + */ + FIRAuthErrorCodeMalformedJWT = 18000, +} NS_SWIFT_NAME(AuthErrorCode); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthSettings.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthSettings.h new file mode 100644 index 00000000..60ba7109 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthSettings.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthSettings + @brief Determines settings related to an auth object. + */ +NS_SWIFT_NAME(AuthSettings) +@interface FIRAuthSettings : NSObject + +/** @property appVerificationDisabledForTesting + @brief Flag to determine whether app verification should be disabled for testing or not. + */ +@property(nonatomic, assign, getter=isAppVerificationDisabledForTesting) + BOOL appVerificationDisabledForTesting; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthTokenResult.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthTokenResult.h new file mode 100644 index 00000000..3c98c5f8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthTokenResult.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthTokenResult + @brief A data class containing the ID token JWT string and other properties associated with the + token including the decoded payload claims. + */ +NS_SWIFT_NAME(AuthTokenResult) +@interface FIRAuthTokenResult : NSObject + +/** @property token + @brief Stores the JWT string of the ID token. + */ +@property(nonatomic, readonly) NSString *token; + +/** @property expirationDate + @brief Stores the ID token's expiration date. + */ +@property(nonatomic, readonly) NSDate *expirationDate; + +/** @property authDate + @brief Stores the ID token's authentication date. + @remarks This is the date the user was signed in and NOT the date the token was refreshed. + */ +@property(nonatomic, readonly) NSDate *authDate; + +/** @property issuedAtDate + @brief Stores the date that the ID token was issued. + @remarks This is the date last refreshed and NOT the last authentication date. + */ +@property(nonatomic, readonly) NSDate *issuedAtDate; + +/** @property signInProvider + @brief Stores sign-in provider through which the token was obtained. + @remarks This does not necessarily map to provider IDs. + */ +@property(nonatomic, readonly) NSString *signInProvider; + +/** @property signInSecondFactor + @brief Stores sign-in second factor through which the token was obtained. + */ +@property(nonatomic, readonly) NSString *signInSecondFactor; + +/** @property claims + @brief Stores the entire payload of claims found on the ID token. This includes the standard + reserved claims as well as custom claims set by the developer via the Admin SDK. + */ +@property(nonatomic, readonly) NSDictionary *claims; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthUIDelegate.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthUIDelegate.h new file mode 100644 index 00000000..43b7fb2e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRAuthUIDelegate.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import + +@class UIViewController; + +NS_ASSUME_NONNULL_BEGIN + +/** @protocol FIRAuthUIDelegate + @brief A protocol to handle user interface interactions for Firebase Auth. + */ +NS_SWIFT_NAME(AuthUIDelegate) +@protocol FIRAuthUIDelegate + +/** @fn presentViewController:animated:completion: + @brief If implemented, this method will be invoked when Firebase Auth needs to display a view + controller. + @param viewControllerToPresent The view controller to be presented. + @param flag Decides whether the view controller presentation should be animated or not. + @param completion The block to execute after the presentation finishes. This block has no return + value and takes no parameters. +*/ +- (void)presentViewController:(UIViewController *)viewControllerToPresent + animated:(BOOL)flag + completion:(void (^_Nullable)(void))completion; + +/** @fn dismissViewControllerAnimated:completion: + @brief If implemented, this method will be invoked when Firebase Auth needs to display a view + controller. + @param flag Decides whether removing the view controller should be animated or not. + @param completion The block to execute after the presentation finishes. This block has no return + value and takes no parameters. +*/ +- (void)dismissViewControllerAnimated:(BOOL)flag + completion:(void (^_Nullable)(void))completion + NS_SWIFT_NAME(dismiss(animated:completion:)); + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIREmailAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIREmailAuthProvider.h new file mode 100644 index 00000000..aac0bf0a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIREmailAuthProvider.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the email & password identity provider. + */ +extern NSString *const FIREmailAuthProviderID NS_SWIFT_NAME(EmailAuthProviderID); + +/** + @brief A string constant identifying the email-link sign-in method. + */ +extern NSString *const FIREmailLinkAuthSignInMethod NS_SWIFT_NAME(EmailLinkAuthSignInMethod); + +/** + @brief A string constant identifying the email & password sign-in method. + */ +extern NSString *const FIREmailPasswordAuthSignInMethod + NS_SWIFT_NAME(EmailPasswordAuthSignInMethod); + +/** @class FIREmailAuthProvider + @brief A concrete implementation of `FIRAuthProvider` for Email & Password Sign In. + */ +NS_SWIFT_NAME(EmailAuthProvider) +@interface FIREmailAuthProvider : NSObject + +/** @fn credentialWithEmail:password: + @brief Creates an `FIRAuthCredential` for an email & password sign in. + + @param email The user's email address. + @param password The user's password. + @return A FIRAuthCredential containing the email & password credential. + */ ++ (FIRAuthCredential *)credentialWithEmail:(NSString *)email password:(NSString *)password; + +/** @fn credentialWithEmail:Link: + @brief Creates an `FIRAuthCredential` for an email & link sign in. + + @param email The user's email address. + @param link The email sign-in link. + @return A FIRAuthCredential containing the email & link credential. + */ ++ (FIRAuthCredential *)credentialWithEmail:(NSString *)email link:(NSString *)link; + +/** @fn init + @brief This class is not meant to be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFacebookAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFacebookAuthProvider.h new file mode 100644 index 00000000..75efe13f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFacebookAuthProvider.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the Facebook identity provider. + */ +extern NSString *const FIRFacebookAuthProviderID NS_SWIFT_NAME(FacebookAuthProviderID); + +/** + @brief A string constant identifying the Facebook sign-in method. + */ +extern NSString *const _Nonnull FIRFacebookAuthSignInMethod NS_SWIFT_NAME(FacebookAuthSignInMethod); + +/** @class FIRFacebookAuthProvider + @brief Utility class for constructing Facebook credentials. + */ +NS_SWIFT_NAME(FacebookAuthProvider) +@interface FIRFacebookAuthProvider : NSObject + +/** @fn credentialWithAccessToken: + @brief Creates an `FIRAuthCredential` for a Facebook sign in. + + @param accessToken The Access Token from Facebook. + @return A FIRAuthCredential containing the Facebook credentials. + */ ++ (FIRAuthCredential *)credentialWithAccessToken:(NSString *)accessToken; + +/** @fn init + @brief This class should not be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFederatedAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFederatedAuthProvider.h new file mode 100644 index 00000000..3effcacb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRFederatedAuthProvider.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if TARGET_OS_IOS +#import "FIRAuthUIDelegate.h" +#endif // TARGET_OS_IOS + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + Utility type for constructing federated auth provider credentials. + */ +NS_SWIFT_NAME(FederatedAuthProvider) +@protocol FIRFederatedAuthProvider + +/** @typedef FIRAuthCredentialCallback + @brief The type of block invoked when obtaining an auth credential. + @param credential The credential obtained. + @param error The error that occurred if any. + */ +typedef void (^FIRAuthCredentialCallback)(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) + NS_SWIFT_NAME(AuthCredentialCallback); + +#if TARGET_OS_IOS +/** @fn getCredentialWithUIDelegate:completion: + @brief Used to obtain an auth credential via a mobile web flow. + @param UIDelegate An optional UI delegate used to presenet the mobile web flow. + @param completion Optionally; a block which is invoked asynchronously on the main thread when + the mobile web flow is completed. + */ +- (void)getCredentialWithUIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthCredentialCallback)completion; +#endif // TARGET_OS_IOS + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGameCenterAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGameCenterAuthProvider.h new file mode 100644 index 00000000..f84492d6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGameCenterAuthProvider.h @@ -0,0 +1,62 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the Game Center identity provider. + */ +extern NSString *const FIRGameCenterAuthProviderID NS_SWIFT_NAME(GameCenterAuthProviderID); + +/** + @brief A string constant identifying the Game Center sign-in method. + */ +extern NSString *const _Nonnull FIRGameCenterAuthSignInMethod NS_SWIFT_NAME( + GameCenterAuthSignInMethod); + +/** @typedef FIRGameCenterCredentialCallback + @brief The type of block invoked when the Game Center credential code has finished. + @param credential On success, the credential will be provided, nil otherwise. + @param error On error, the error that occurred, nil otherwise. + */ +typedef void (^FIRGameCenterCredentialCallback)(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) + NS_SWIFT_NAME(GameCenterCredentialCallback); + +/** @class FIRGameCenterAuthProvider + @brief A concrete implementation of @c FIRAuthProvider for Game Center Sign In. + */ +NS_SWIFT_NAME(GameCenterAuthProvider) +@interface FIRGameCenterAuthProvider : NSObject + +/** @fn getCredentialWithCompletion: + @brief Creates a @c FIRAuthCredential for a Game Center sign in. + */ ++ (void)getCredentialWithCompletion:(FIRGameCenterCredentialCallback)completion + NS_SWIFT_NAME(getCredential(completion:)); + +/** @fn init + @brief This class is not meant to be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGitHubAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGitHubAuthProvider.h new file mode 100644 index 00000000..0577c7bc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGitHubAuthProvider.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the GitHub identity provider. + */ +extern NSString *const FIRGitHubAuthProviderID NS_SWIFT_NAME(GitHubAuthProviderID); + +/** + @brief A string constant identifying the GitHub sign-in method. + */ +extern NSString *const _Nonnull FIRGitHubAuthSignInMethod NS_SWIFT_NAME(GitHubAuthSignInMethod); + +/** @class FIRGitHubAuthProvider + @brief Utility class for constructing GitHub credentials. + */ +NS_SWIFT_NAME(GitHubAuthProvider) +@interface FIRGitHubAuthProvider : NSObject + +/** @fn credentialWithToken: + @brief Creates an `FIRAuthCredential` for a GitHub sign in. + + @param token The GitHub OAuth access token. + @return A FIRAuthCredential containing the GitHub credential. + */ ++ (FIRAuthCredential *)credentialWithToken:(NSString *)token; + +/** @fn init + @brief This class is not meant to be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGoogleAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGoogleAuthProvider.h new file mode 100644 index 00000000..7d6fa226 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRGoogleAuthProvider.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the Google identity provider. + */ +extern NSString *const FIRGoogleAuthProviderID NS_SWIFT_NAME(GoogleAuthProviderID); + +/** + @brief A string constant identifying the Google sign-in method. + */ +extern NSString *const _Nonnull FIRGoogleAuthSignInMethod NS_SWIFT_NAME(GoogleAuthSignInMethod); + +/** @class FIRGoogleAuthProvider + @brief Utility class for constructing Google Sign In credentials. + */ +NS_SWIFT_NAME(GoogleAuthProvider) +@interface FIRGoogleAuthProvider : NSObject + +/** @fn credentialWithIDToken:accessToken: + @brief Creates an `FIRAuthCredential` for a Google sign in. + + @param IDToken The ID Token from Google. + @param accessToken The Access Token from Google. + @return A FIRAuthCredential containing the Google credentials. + */ ++ (FIRAuthCredential *)credentialWithIDToken:(NSString *)IDToken + accessToken:(NSString *)accessToken; + +/** @fn init + @brief This class should not be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactor.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactor.h new file mode 100644 index 00000000..1794b551 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactor.h @@ -0,0 +1,89 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FIRAuth.h" +#import "FIRMultiFactorAssertion.h" +#import "FIRMultiFactorInfo.h" +#import "FIRMultiFactorSession.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRMultiFactorSessionCallback + @brief The callback that triggered when a developer calls `getSessionWithCompletion`. + @param session The multi factor session returned, if any. + @param error The error which occurred, if any. +*/ +typedef void (^FIRMultiFactorSessionCallback)(FIRMultiFactorSession *_Nullable session, + NSError *_Nullable error) + NS_SWIFT_NAME(MultiFactorSessionCallback); + +/** + @brief The string identifier for second factors. e.g. "phone". +*/ +extern NSString *const _Nonnull FIRPhoneMultiFactorID NS_SWIFT_NAME(PhoneMultiFactorID); + +/** @class FIRMultiFactor + @brief The interface defining the multi factor related properties and operations pertaining to a + user. +*/ +NS_SWIFT_NAME(MultiFactor) +@interface FIRMultiFactor : NSObject + +@property(nonatomic, readonly) NSArray *enrolledFactors; + +/** @fn getSessionWithCompletion: + @brief Get a session for a second factor enrollment operation. + @param completion A block with the session identifier for a second factor enrollment operation. + This is used to identify the current user trying to enroll a second factor. +*/ +- (void)getSessionWithCompletion:(nullable FIRMultiFactorSessionCallback)completion; + +/** @fn enrollWithAssertion:displayName:completion: + @brief Enrolls a second factor as identified by the `FIRMultiFactorAssertion` parameter for the + current user. + @param displayName An optional display name associated with the multi factor to enroll. + @param completion The block invoked when the request is complete, or fails. +*/ +- (void)enrollWithAssertion:(FIRMultiFactorAssertion *)assertion + displayName:(nullable NSString *)displayName + completion:(nullable FIRAuthVoidErrorCallback)completion; + +/** @fn unenrollWithInfo:completion: + @brief Unenroll the given multi factor. + @param completion The block invoked when the request to send the verification email is complete, + or fails. +*/ +- (void)unenrollWithInfo:(FIRMultiFactorInfo *)factorInfo + completion:(nullable FIRAuthVoidErrorCallback)completion; + +/** @fn unenrollWithFactorUID:completion: + @brief Unenroll the given multi factor. + @param completion The block invoked when the request to send the verification email is complete, + or fails. +*/ +- (void)unenrollWithFactorUID:(NSString *)factorUID + completion:(nullable FIRAuthVoidErrorCallback)completion; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorAssertion.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorAssertion.h new file mode 100644 index 00000000..536289c6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorAssertion.h @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRMultiFactorAssertion + @brief The base class for asserting ownership of a second factor. This is equivalent to the + AuthCredential class. +*/ +NS_SWIFT_NAME(MultiFactorAssertion) +@interface FIRMultiFactorAssertion : NSObject + +/** + @brief The second factor identifier for this opaque object asserting a second factor. +*/ +@property(nonatomic, readonly, nonnull) NSString *factorID; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorInfo.h new file mode 100644 index 00000000..df7579e0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorInfo.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRMultiFactorInfo + @brief Safe public structure used to represent a second factor entity from a client perspective. +*/ +NS_SWIFT_NAME(MultiFactorInfo) +@interface FIRMultiFactorInfo : NSObject + +/** + @brief The multi-factor enrollment ID. +*/ +@property(nonatomic, readonly) NSString *UID; + +/** + @brief The user friendly name of the current second factor. +*/ +@property(nonatomic, readonly, nullable) NSString *displayName; + +/** + @brief The second factor enrollment date. +*/ +@property(nonatomic, readonly) NSDate *enrollmentDate; + +/** + @brief The identifier of the second factor. +*/ +@property(nonatomic, readonly) NSString *factorID; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorResolver.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorResolver.h new file mode 100644 index 00000000..5e040f16 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorResolver.h @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import "FIRMultiFactor.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRMultiFactorResolver + @brief The data structure used to help developers resolve 2nd factor requirements on users that + have opted in to 2 factor authentication. +*/ +NS_SWIFT_NAME(MultiFactorResolver) +@interface FIRMultiFactorResolver : NSObject + +/** + @brief The opaque session identifier for the current sign-in flow. +*/ +@property(nonatomic, readonly) FIRMultiFactorSession *session; + +/** + @brief The list of hints for the second factors needed to complete the sign-in for the current + session. +*/ +@property(nonatomic, readonly) NSArray *hints NS_SWIFT_NAME(hints); + +/** + @brief The Auth reference for the current FIRMultiResolver. +*/ +@property(nonatomic, readonly) FIRAuth *auth; + +/** @fn resolveSignInWithAssertion:completion: + @brief A helper function to help users complete sign in with a second factor using an + FIRMultiFactorAssertion confirming the user successfully completed the second factor + challenge. + @param completion The block invoked when the request is complete, or fails. +*/ +- (void)resolveSignInWithAssertion:(FIRMultiFactorAssertion *)assertion + completion:(nullable FIRAuthDataResultCallback)completion; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorSession.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorSession.h new file mode 100644 index 00000000..c7234b23 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRMultiFactorSession.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRMultiFactorSession + @brief Opaque object that identifies the current session to enroll a second factor or to + complete sign in when previously enrolled. + */ +NS_SWIFT_NAME(MultiFactorSession) +@interface FIRMultiFactorSession : NSObject + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthCredential.h new file mode 100644 index 00000000..94abe4f2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthCredential.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRAuthCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIROAuthCredential + @brief Internal implementation of FIRAuthCredential for generic credentials. + */ +NS_SWIFT_NAME(OAuthCredential) +@interface FIROAuthCredential : FIRAuthCredential + +/** @property IDToken + @brief The ID Token associated with this credential. + */ +@property(nonatomic, readonly, nullable) NSString *IDToken; + +/** @property accessToken + @brief The access token associated with this credential. + */ +@property(nonatomic, readonly, nullable) NSString *accessToken; + +/** @property secret + @brief The secret associated with this credential. This will be nil for OAuth 2.0 providers. + @detail OAuthCredential already exposes a providerId getter. This will help the developer + determine whether an access token/secret pair is needed. + */ +@property(nonatomic, readonly, nullable) NSString *secret; + +/** @fn init + @brief This class is not supposed to be instantiated directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthProvider.h new file mode 100644 index 00000000..9b6f4f3d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIROAuthProvider.h @@ -0,0 +1,124 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRFederatedAuthProvider.h" + +@class FIRAuth; +@class FIROAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIROAuthProvider + @brief A concrete implementation of `FIRAuthProvider` for generic OAuth Providers. + */ +NS_SWIFT_NAME(OAuthProvider) +@interface FIROAuthProvider : NSObject + +/** @property scopes + @brief Array used to configure the OAuth scopes. + */ +@property(nonatomic, copy, nullable) NSArray *scopes; + +/** @property customParameters + @brief Dictionary used to configure the OAuth custom parameters. + */ +@property(nonatomic, copy, nullable) NSDictionary *customParameters; + +/** @property providerID + @brief The provider ID indicating the specific OAuth provider this OAuthProvider instance + represents. + */ +@property(nonatomic, copy, readonly) NSString *providerID; + +/** @fn providerWithProviderID: + @param providerID The provider ID of the IDP for which this auth provider instance will be + configured. + @return An instance of FIROAuthProvider corresponding to the specified provider ID. + */ ++ (FIROAuthProvider *)providerWithProviderID:(NSString *)providerID; + +/** @fn providerWithProviderID:auth: + @param providerID The provider ID of the IDP for which this auth provider instance will be + configured. + @param auth The auth instance to be associated with the FIROAuthProvider instance. + @return An instance of FIROAuthProvider corresponding to the specified provider ID. + */ ++ (FIROAuthProvider *)providerWithProviderID:(NSString *)providerID auth:(FIRAuth *)auth; + +/** @fn credentialWithProviderID:IDToken:accessToken: + @brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID, ID + token and access token. + + @param providerID The provider ID associated with the Auth credential being created. + @param IDToken The IDToken associated with the Auth credential being created. + @param accessToken The accessstoken associated with the Auth credential be created, if + available. + @return A FIRAuthCredential for the specified provider ID, ID token and access token. + */ ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + accessToken:(nullable NSString *)accessToken; + +/** @fn credentialWithProviderID:accessToken: + @brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID using + an ID token. + + @param providerID The provider ID associated with the Auth credential being created. + @param accessToken The accessstoken associated with the Auth credential be created + @return A FIRAuthCredential. + */ ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + accessToken:(NSString *)accessToken; + +/** @fn credentialWithProviderID:IDToken:rawNonce:accessToken: + @brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID, ID + token, raw nonce and access token. + + @param providerID The provider ID associated with the Auth credential being created. + @param IDToken The IDToken associated with the Auth credential being created. + @param rawNonce The raw nonce associated with the Auth credential being created. + @param accessToken The accessstoken associated with the Auth credential be created, if + available. + @return A FIRAuthCredential for the specified provider ID, ID token and access token. + */ ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce + accessToken:(nullable NSString *)accessToken; + +/** @fn credentialWithProviderID:IDToken:rawNonce: + @brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID using + an ID token and raw nonce. + + @param providerID The provider ID associated with the Auth credential being created. + @param IDToken The IDToken associated with the Auth credential being created. + @param rawNonce The raw nonce associated with the Auth credential being created. + @return A FIRAuthCredential. + */ ++ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID + IDToken:(NSString *)IDToken + rawNonce:(nullable NSString *)rawNonce; + +/** @fn init + @brief This class is not meant to be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthCredential.h new file mode 100644 index 00000000..dba06b9f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthCredential.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FIRAuthCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRPhoneAuthCredential + @brief Implementation of FIRAuthCredential for Phone Auth credentials. + */ +NS_SWIFT_NAME(PhoneAuthCredential) +@interface FIRPhoneAuthCredential : FIRAuthCredential + +/** @fn init + @brief This class is not supposed to be instantiated directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthProvider.h new file mode 100644 index 00000000..a3e2ee37 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneAuthProvider.h @@ -0,0 +1,141 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +@class FIRAuth; +@class FIRMultiFactorSession; +@class FIRPhoneAuthCredential; +@class FIRPhoneMultiFactorInfo; +@protocol FIRAuthUIDelegate; + +NS_ASSUME_NONNULL_BEGIN + +/** @var FIRPhoneAuthProviderID + @brief A string constant identifying the phone identity provider. + */ +extern NSString *const FIRPhoneAuthProviderID NS_SWIFT_NAME(PhoneAuthProviderID); + +/** @var FIRPhoneAuthProviderID + @brief A string constant identifying the phone sign-in method. + */ +extern NSString *const _Nonnull FIRPhoneAuthSignInMethod NS_SWIFT_NAME(PhoneAuthSignInMethod); + +/** @typedef FIRVerificationResultCallback + @brief The type of block invoked when a request to send a verification code has finished. + + @param verificationID On success, the verification ID provided, nil otherwise. + @param error On error, the error that occurred, nil otherwise. + */ +typedef void (^FIRVerificationResultCallback)(NSString *_Nullable verificationID, + NSError *_Nullable error) + NS_SWIFT_NAME(VerificationResultCallback); + +/** @class FIRPhoneAuthProvider + @brief A concrete implementation of `FIRAuthProvider` for phone auth providers. + */ +NS_SWIFT_NAME(PhoneAuthProvider) +@interface FIRPhoneAuthProvider : NSObject + +/** @fn provider + @brief Returns an instance of `FIRPhoneAuthProvider` for the default `FIRAuth` object. + */ ++ (instancetype)provider NS_SWIFT_NAME(provider()); + +/** @fn providerWithAuth: + @brief Returns an instance of `FIRPhoneAuthProvider` for the provided `FIRAuth` object. + @param auth The auth object to associate with the phone auth provider instance. + */ ++ (instancetype)providerWithAuth:(FIRAuth *)auth NS_SWIFT_NAME(provider(auth:)); + +/** @fn verifyPhoneNumber:UIDelegate:completion: + @brief Starts the phone number authentication flow by sending a verification code to the + specified phone number. + @param phoneNumber The phone number to be verified. + @param UIDelegate An object used to present the SFSafariViewController. The object is retained + by this method until the completion block is executed. + @param completion The callback to be invoked when the verification flow is finished. + @remarks Possible error codes: + + + `FIRAuthErrorCodeCaptchaCheckFailed` - Indicates that the reCAPTCHA token obtained by + the Firebase Auth is invalid or has expired. + + `FIRAuthErrorCodeQuotaExceeded` - Indicates that the phone verification quota for this + project has been exceeded. + + `FIRAuthErrorCodeInvalidPhoneNumber` - Indicates that the phone number provided is + invalid. + + `FIRAuthErrorCodeMissingPhoneNumber` - Indicates that a phone number was not provided. + */ +- (void)verifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRVerificationResultCallback)completion; + +/** @fn verifyPhoneNumber:UIDelegate:multiFactorSession:completion: + @brief Verify ownership of the second factor phone number by the current user. + @param phoneNumber The phone number to be verified. + @param UIDelegate An object used to present the SFSafariViewController. The object is retained + by this method until the completion block is executed. + @param session A session to identify the MFA flow. For enrollment, this identifies the user + trying to enroll. For sign-in, this identifies that the user already passed the first + factor challenge. + @param completion The callback to be invoked when the verification flow is finished. +*/ +- (void)verifyPhoneNumber:(NSString *)phoneNumber + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + completion:(nullable FIRVerificationResultCallback)completion; + +/** @fn verifyPhoneNumberWithMultiFactorInfo:UIDelegate:multiFactorSession:completion: + @brief Verify ownership of the second factor phone number by the current user. + @param phoneMultiFactorInfo The phone multi factor whose number need to be verified. + @param UIDelegate An object used to present the SFSafariViewController. The object is retained + by this method until the completion block is executed. + @param session A session to identify the MFA flow. For enrollment, this identifies the user + trying to enroll. For sign-in, this identifies that the user already passed the first + factor challenge. + @param completion The callback to be invoked when the verification flow is finished. +*/ +- (void)verifyPhoneNumberWithMultiFactorInfo:(FIRPhoneMultiFactorInfo *)phoneMultiFactorInfo + UIDelegate:(nullable id)UIDelegate + multiFactorSession:(nullable FIRMultiFactorSession *)session + completion:(nullable FIRVerificationResultCallback)completion; + +/** @fn credentialWithVerificationID:verificationCode: + @brief Creates an `FIRAuthCredential` for the phone number provider identified by the + verification ID and verification code. + + @param verificationID The verification ID obtained from invoking + verifyPhoneNumber:completion: + @param verificationCode The verification code obtained from the user. + @return The corresponding phone auth credential for the verification ID and verification code + provided. + */ +- (FIRPhoneAuthCredential *)credentialWithVerificationID:(NSString *)verificationID + verificationCode:(NSString *)verificationCode; + +/** @fn init + @brief Please use the `provider` or `providerWithAuth:` methods to obtain an instance of + `FIRPhoneAuthProvider`. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorAssertion.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorAssertion.h new file mode 100644 index 00000000..30cc2c45 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorAssertion.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FIRMultiFactorAssertion.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRPhoneMultiFactorAssertion + @brief The subclass of base class FIRMultiFactorAssertion, used to assert ownership of a phone + second factor. +*/ +NS_SWIFT_NAME(PhoneMultiFactorAssertion) +@interface FIRPhoneMultiFactorAssertion : FIRMultiFactorAssertion + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorGenerator.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorGenerator.h new file mode 100644 index 00000000..8e9cc7b3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorGenerator.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FIRPhoneAuthCredential.h" +#import "FIRPhoneMultiFactorAssertion.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRPhoneMultiFactorGenerator + @brief The data structure used to help initialize an assertion for a second factor entity to the + Firebase Auth/CICP server. Depending on the type of second factor, this will help generate + the assertion. +*/ +NS_SWIFT_NAME(PhoneMultiFactorGenerator) +@interface FIRPhoneMultiFactorGenerator : NSObject + +/** @fn assertionWithCredential: + @brief Initializes the MFA assertion to confirm ownership of the phone second factor. Note that + this API is used for both enrolling and signing in with a phone second factor. + @param phoneAuthCredential The phone auth credential used for multi factor flows. +*/ ++ (FIRPhoneMultiFactorAssertion *)assertionWithCredential: + (FIRPhoneAuthCredential *)phoneAuthCredential; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorInfo.h new file mode 100644 index 00000000..30f02132 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRPhoneMultiFactorInfo.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +#import "FIRMultiFactorInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRPhoneMultiFactorInfo + @brief Extends the FIRMultiFactorInfo class for phone number second factors. + The identifier of this second factor is "phone". +*/ +NS_SWIFT_NAME(PhoneMultiFactorInfo) +@interface FIRPhoneMultiFactorInfo : FIRMultiFactorInfo + +/** + @brief This is the phone number associated with the current second factor. +*/ +@property(nonatomic, readonly, nonnull) NSString *phoneNumber; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRTwitterAuthProvider.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRTwitterAuthProvider.h new file mode 100644 index 00000000..0f1b28d7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRTwitterAuthProvider.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief A string constant identifying the Twitter identity provider. + */ +extern NSString *const FIRTwitterAuthProviderID NS_SWIFT_NAME(TwitterAuthProviderID); +/** + @brief A string constant identifying the Twitter sign-in method. + */ +extern NSString *const _Nonnull FIRTwitterAuthSignInMethod NS_SWIFT_NAME(TwitterAuthSignInMethod); + +/** @class FIRTwitterAuthProvider + @brief Utility class for constructing Twitter credentials. + */ +NS_SWIFT_NAME(TwitterAuthProvider) +@interface FIRTwitterAuthProvider : NSObject + +/** @fn credentialWithToken:secret: + @brief Creates an `FIRAuthCredential` for a Twitter sign in. + + @param token The Twitter OAuth token. + @param secret The Twitter OAuth secret. + @return A FIRAuthCredential containing the Twitter credential. + */ ++ (FIRAuthCredential *)credentialWithToken:(NSString *)token secret:(NSString *)secret; + +/** @fn init + @brief This class is not meant to be initialized. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUser.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUser.h new file mode 100644 index 00000000..15580b8e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUser.h @@ -0,0 +1,557 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRAuth.h" +#import "FIRAuthDataResult.h" +#import "FIRMultiFactor.h" +#import "FIRUserInfo.h" + +@class FIRAuthTokenResult; +@class FIRPhoneAuthCredential; +@class FIRUserProfileChangeRequest; +@class FIRUserMetadata; +@protocol FIRAuthUIDelegate; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthTokenCallback + @brief The type of block called when a token is ready for use. + @see FIRUser.getIDTokenWithCompletion: + @see FIRUser.getIDTokenForcingRefresh:withCompletion: + + @param token Optionally; an access token if the request was successful. + @param error Optionally; the error which occurred - or nil if the request was successful. + + @remarks One of: `token` or `error` will always be non-nil. + */ +typedef void (^FIRAuthTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(AuthTokenCallback); + +/** @typedef FIRAuthTokenResultCallback + @brief The type of block called when a token is ready for use. + @see FIRUser.getIDTokenResultWithCompletion: + @see FIRUser.getIDTokenResultForcingRefresh:withCompletion: + + @param tokenResult Optionally; an object containing the raw access token string as well as other + useful data pertaining to the token. + @param error Optionally; the error which occurred - or nil if the request was successful. + + @remarks One of: `token` or `error` will always be non-nil. + */ +typedef void (^FIRAuthTokenResultCallback)(FIRAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) + NS_SWIFT_NAME(AuthTokenResultCallback); + +/** @typedef FIRUserProfileChangeCallback + @brief The type of block called when a user profile change has finished. + + @param error Optionally; the error which occurred - or nil if the request was successful. + */ +typedef void (^FIRUserProfileChangeCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(UserProfileChangeCallback); + +/** @typedef FIRSendEmailVerificationCallback + @brief The type of block called when a request to send an email verification has finished. + + @param error Optionally; the error which occurred - or nil if the request was successful. + */ +typedef void (^FIRSendEmailVerificationCallback)(NSError *_Nullable error) + NS_SWIFT_NAME(SendEmailVerificationCallback); + +/** @class FIRUser + @brief Represents a user. Firebase Auth does not attempt to validate users + when loading them from the keychain. Invalidated users (such as those + whose passwords have been changed on another client) are automatically + logged out when an auth-dependent operation is attempted or when the + ID token is automatically refreshed. + @remarks This class is thread-safe. + */ +NS_SWIFT_NAME(User) +@interface FIRUser : NSObject + +/** @property anonymous + @brief Indicates the user represents an anonymous user. + */ +@property(nonatomic, readonly, getter=isAnonymous) BOOL anonymous; + +/** @property emailVerified + @brief Indicates the email address associated with this user has been verified. + */ +@property(nonatomic, readonly, getter=isEmailVerified) BOOL emailVerified; + +/** @property refreshToken + @brief A refresh token; useful for obtaining new access tokens independently. + @remarks This property should only be used for advanced scenarios, and is not typically needed. + */ +@property(nonatomic, readonly, nullable) NSString *refreshToken; + +/** @property providerData + @brief Profile data for each identity provider, if any. + @remarks This data is cached on sign-in and updated when linking or unlinking. + */ +@property(nonatomic, readonly, nonnull) NSArray> *providerData; + +/** @property metadata + @brief Metadata associated with the Firebase user in question. + */ +@property(nonatomic, readonly, nonnull) FIRUserMetadata *metadata; + +#if TARGET_OS_IOS +/** @property multiFactor + @brief Multi factor object associated with the user. +*/ +@property(nonatomic, readonly, nonnull) FIRMultiFactor *multiFactor; +#endif + +/** @fn init + @brief This class should not be instantiated. + @remarks To retrieve the current user, use `FIRAuth.currentUser`. To sign a user + in or out, use the methods on `FIRAuth`. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn updateEmail:completion: + @brief Updates the email address for the user. On success, the cached user profile data is + updated. + @remarks May fail if there is already an account with this email address that was created using + email and password authentication. + + @param email The email address for the user. + @param completion Optionally; the block invoked when the user profile change has finished. + Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + `FIRAuthErrorCodeEmailAlreadyInUse` - Indicates the email is already in use by another + account. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + `FIRAuthErrorCodeRequiresRecentLogin` - Updating a user’s email is a security + sensitive operation that requires a recent login from the user. This error indicates + the user has not signed in recently enough. To resolve, reauthenticate the user by + invoking reauthenticateWithCredential:completion: on FIRUser. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)updateEmail:(NSString *)email + completion:(nullable FIRUserProfileChangeCallback)completion + NS_SWIFT_NAME(updateEmail(to:completion:)); + +/** @fn updatePassword:completion: + @brief Updates the password for the user. On success, the cached user profile data is updated. + + @param password The new password for the user. + @param completion Optionally; the block invoked when the user profile change has finished. + Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates the administrator disabled + sign in with the specified identity provider. + + `FIRAuthErrorCodeRequiresRecentLogin` - Updating a user’s password is a security + sensitive operation that requires a recent login from the user. This error indicates + the user has not signed in recently enough. To resolve, reauthenticate the user by + invoking reauthenticateWithCredential:completion: on FIRUser. + + `FIRAuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is + considered too weak. The NSLocalizedFailureReasonErrorKey field in the NSError.userInfo + dictionary object will contain more detailed explanation that can be shown to the user. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)updatePassword:(NSString *)password + completion:(nullable FIRUserProfileChangeCallback)completion + NS_SWIFT_NAME(updatePassword(to:completion:)); + +#if TARGET_OS_IOS +/** @fn updatePhoneNumberCredential:completion: + @brief Updates the phone number for the user. On success, the cached user profile data is + updated. + + @param phoneNumberCredential The new phone number credential corresponding to the phone number + to be added to the Firebase account, if a phone number is already linked to the account this + new phone number will replace it. + @param completion Optionally; the block invoked when the user profile change has finished. + Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeRequiresRecentLogin` - Updating a user’s phone number is a security + sensitive operation that requires a recent login from the user. This error indicates + the user has not signed in recently enough. To resolve, reauthenticate the user by + invoking reauthenticateWithCredential:completion: on FIRUser. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)updatePhoneNumberCredential:(FIRPhoneAuthCredential *)phoneNumberCredential + completion:(nullable FIRUserProfileChangeCallback)completion; +#endif + +/** @fn profileChangeRequest + @brief Creates an object which may be used to change the user's profile data. + + @remarks Set the properties of the returned object, then call + `FIRUserProfileChangeRequest.commitChangesWithCallback:` to perform the updates atomically. + + @return An object which may be used to change the user's profile data atomically. + */ +- (FIRUserProfileChangeRequest *)profileChangeRequest NS_SWIFT_NAME(createProfileChangeRequest()); + +/** @fn reloadWithCompletion: + @brief Reloads the user's profile data from the server. + + @param completion Optionally; the block invoked when the reload has finished. Invoked + asynchronously on the main thread in the future. + + @remarks May fail with a `FIRAuthErrorCodeRequiresRecentLogin` error code. In this case + you should call `FIRUser.reauthenticateWithCredential:completion:` before re-invoking + `FIRUser.updateEmail:completion:`. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)reloadWithCompletion:(nullable FIRUserProfileChangeCallback)completion; + +/** @fn reauthenticateWithCredential:completion: + @brief Renews the user's authentication tokens by validating a fresh set of credentials supplied + by the user and returns additional identity provider data. + + @param credential A user-supplied credential, which will be validated by the server. This can be + a successful third-party identity provider sign-in, or an email address and password. + @param completion Optionally; the block invoked when the re-authentication operation has + finished. Invoked asynchronously on the main thread in the future. + + @remarks If the user associated with the supplied credential is different from the current user, + or if the validation of the supplied credentials fails; an error is returned and the current + user remains signed in. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidCredential` - Indicates the supplied credential is invalid. + This could happen if it has expired or it is malformed. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts with the + identity provider represented by the credential are not enabled. Enable them in the + Auth section of the Firebase console. + + `FIRAuthErrorCodeEmailAlreadyInUse` - Indicates the email asserted by the credential + (e.g. the email in a Facebook access token) is already in use by an existing account, + that cannot be authenticated with this method. Call fetchProvidersForEmail for + this user’s email and then prompt them to sign in with any of the sign-in providers + returned. This error will only be thrown if the "One account per email address" + setting is enabled in the Firebase console, under Auth settings. Please note that the + error code raised in this specific situation may not be the same on Web and Android. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted reauthentication with + an incorrect password, if credential is of the type EmailPasswordAuthCredential. + + `FIRAuthErrorCodeUserMismatch` - Indicates that an attempt was made to + reauthenticate with a user which is not the current user. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)reauthenticateWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn reauthenticateAndRetrieveDataWithCredential:completion: + @brief Please use linkWithCredential:completion: for Objective-C + or link(withCredential:completion:) for Swift instead. + */ +- (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion + DEPRECATED_MSG_ATTRIBUTE("Please use reauthenticateWithCredential:completion: for" + " Objective-C or reauthenticate(withCredential:completion:)" + " for Swift instead."); + +/** @fn reauthenticateWithProvider:UIDelegate:completion: + @brief Renews the user's authentication using the provided auth provider instance. + + @param provider An instance of an auth provider used to initiate the reauthenticate flow. + @param UIDelegate Optionally an instance of a class conforming to the FIRAuthUIDelegate + protocol, this is used for presenting the web context. If nil, a default FIRAuthUIDelegate + will be used. + @param completion Optionally; a block which is invoked when the reauthenticate flow finishes, or + is canceled. Invoked asynchronously on the main thread in the future. + */ +// clang-format off +- (void)reauthenticateWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion + NS_SWIFT_NAME(reauthenticate(with:uiDelegate:completion:)) + API_AVAILABLE(ios(8.0)); +// clang-format on + +/** @fn getIDTokenResultWithCompletion: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + + @param completion Optionally; the block invoked when the token is available. Invoked + asynchronously on the main thread in the future. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)getIDTokenResultWithCompletion:(nullable FIRAuthTokenResultCallback)completion + NS_SWIFT_NAME(getIDTokenResult(completion:)); + +/** @fn getIDTokenResultForcingRefresh:completion: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + + @param forceRefresh Forces a token refresh. Useful if the token becomes invalid for some reason + other than an expiration. + @param completion Optionally; the block invoked when the token is available. Invoked + asynchronously on the main thread in the future. + + @remarks The authentication token will be refreshed (by making a network request) if it has + expired, or if `forceRefresh` is YES. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)getIDTokenResultForcingRefresh:(BOOL)forceRefresh + completion:(nullable FIRAuthTokenResultCallback)completion + NS_SWIFT_NAME(getIDTokenResult(forcingRefresh:completion:)); + +/** @fn getIDTokenWithCompletion: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + + @param completion Optionally; the block invoked when the token is available. Invoked + asynchronously on the main thread in the future. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)getIDTokenWithCompletion:(nullable FIRAuthTokenCallback)completion + NS_SWIFT_NAME(getIDToken(completion:)); + +/** @fn getIDTokenForcingRefresh:completion: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + + @param forceRefresh Forces a token refresh. Useful if the token becomes invalid for some reason + other than an expiration. + @param completion Optionally; the block invoked when the token is available. Invoked + asynchronously on the main thread in the future. + + @remarks The authentication token will be refreshed (by making a network request) if it has + expired, or if `forceRefresh` is YES. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ +- (void)getIDTokenForcingRefresh:(BOOL)forceRefresh + completion:(nullable FIRAuthTokenCallback)completion; + +/** @fn linkAndRetrieveDataWithCredential:completion: + @brief Please use linkWithCredential:completion: for Objective-C + or link(withCredential:completion:) for Swift instead. + */ +- (void)linkAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion + DEPRECATED_MSG_ATTRIBUTE("Please use linkWithCredential:completion: for Objective-C " + "or link(withCredential:completion:) for Swift instead."); + +/** @fn linkWithCredential:completion: + @brief Associates a user account from a third-party identity provider with this user and + returns additional identity provider data. + + @param credential The credential for the identity provider. + @param completion Optionally; the block invoked when the unlinking is complete, or fails. + Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeProviderAlreadyLinked` - Indicates an attempt to link a provider of a + type already linked to this account. + + `FIRAuthErrorCodeCredentialAlreadyInUse` - Indicates an attempt to link with a + credential that has already been linked with a different Firebase account. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts with the identity + provider represented by the credential are not enabled. Enable them in the Auth section + of the Firebase console. + + @remarks This method may also return error codes associated with updateEmail:completion: and + updatePassword:completion: on FIRUser. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)linkWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion; + +/** @fn linkWithProvider:UIDelegate:completion: + @brief link the user with the provided auth provider instance. + + @param provider An instance of an auth provider used to initiate the link flow. + @param UIDelegate Optionally an instance of a class conforming to the FIRAuthUIDelegate + protocol, this is used for presenting the web context. If nil, a default FIRAuthUIDelegate + will be used. + @param completion Optionally; a block which is invoked when the link flow finishes, or + is canceled. Invoked asynchronously on the main thread in the future. + */ +// clang-format off +- (void)linkWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion + NS_SWIFT_NAME(link(with:uiDelegate:completion:)) + API_AVAILABLE(ios(8.0)); +// clang-format on + +/** @fn unlinkFromProvider:completion: + @brief Disassociates a user account from a third-party identity provider with this user. + + @param provider The provider ID of the provider to unlink. + @param completion Optionally; the block invoked when the unlinking is complete, or fails. + Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeNoSuchProvider` - Indicates an attempt to unlink a provider + that is not linked to the account. + + `FIRAuthErrorCodeRequiresRecentLogin` - Updating email is a security sensitive + operation that requires a recent login from the user. This error indicates the user + has not signed in recently enough. To resolve, reauthenticate the user by invoking + reauthenticateWithCredential:completion: on FIRUser. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)unlinkFromProvider:(NSString *)provider + completion:(nullable FIRAuthResultCallback)completion; + +/** @fn sendEmailVerificationWithCompletion: + @brief Initiates email verification for the user. + + @param completion Optionally; the block invoked when the request to send an email verification + is complete, or fails. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + `FIRAuthErrorCodeUserNotFound` - Indicates the user account was not found. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + */ +- (void)sendEmailVerificationWithCompletion:(nullable FIRSendEmailVerificationCallback)completion; + +/** @fn sendEmailVerificationWithActionCodeSettings:completion: + @brief Initiates email verification for the user. + + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + `FIRAuthErrorCodeUserNotFound` - Indicates the user account was not found. + + `FIRAuthErrorCodeMissingIosBundleID` - Indicates that the iOS bundle ID is missing when + a iOS App Store ID is provided. + + `FIRAuthErrorCodeMissingAndroidPackageName` - Indicates that the android package name + is missing when the `androidInstallApp` flag is set to true. + + `FIRAuthErrorCodeUnauthorizedDomain` - Indicates that the domain specified in the + continue URL is not whitelisted in the Firebase console. + + `FIRAuthErrorCodeInvalidContinueURI` - Indicates that the domain specified in the + continue URI is not valid. + */ +- (void)sendEmailVerificationWithActionCodeSettings:(FIRActionCodeSettings *)actionCodeSettings + completion: + (nullable FIRSendEmailVerificationCallback)completion; + +/** @fn deleteWithCompletion: + @brief Deletes the user account (also signs out the user, if this was the current user). + + @param completion Optionally; the block invoked when the request to delete the account is + complete, or fails. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeRequiresRecentLogin` - Updating email is a security sensitive + operation that requires a recent login from the user. This error indicates the user + has not signed in recently enough. To resolve, reauthenticate the user by invoking + reauthenticateWithCredential:completion: on FIRUser. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods. + + */ +- (void)deleteWithCompletion:(nullable FIRUserProfileChangeCallback)completion; + +/** @fn sendEmailVerificationBeforeUpdatingEmail:completion: + @brief Send an email to verify the ownership of the account then update to the new email. + @param email The email to be updated to. + @param completion Optionally; the block invoked when the request to send the verification + email is complete, or fails. +*/ +- (void)sendEmailVerificationBeforeUpdatingEmail:(nonnull NSString *)email + completion:(nullable FIRAuthVoidErrorCallback)completion; + +/** @fn sendEmailVerificationBeforeUpdatingEmail:completion: + @brief Send an email to verify the ownership of the account then update to the new email. + @param email The email to be updated to. + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + @param completion Optionally; the block invoked when the request to send the verification + email is complete, or fails. +*/ +- (void)sendEmailVerificationBeforeUpdatingEmail:(nonnull NSString *)email + actionCodeSettings:(nonnull FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRAuthVoidErrorCallback)completion; + +@end + +/** @class FIRUserProfileChangeRequest + @brief Represents an object capable of updating a user's profile data. + @remarks Properties are marked as being part of a profile update when they are set. Setting a + property value to nil is not the same as leaving the property unassigned. + */ +NS_SWIFT_NAME(UserProfileChangeRequest) +@interface FIRUserProfileChangeRequest : NSObject + +/** @fn init + @brief Please use `FIRUser.profileChangeRequest` + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @property displayName + @brief The user's display name. + @remarks It is an error to set this property after calling + `FIRUserProfileChangeRequest.commitChangesWithCallback:` + */ +@property(nonatomic, copy, nullable) NSString *displayName; + +/** @property photoURL + @brief The user's photo URL. + @remarks It is an error to set this property after calling + `FIRUserProfileChangeRequest.commitChangesWithCallback:` + */ +@property(nonatomic, copy, nullable) NSURL *photoURL; + +/** @fn commitChangesWithCompletion: + @brief Commits any pending changes. + @remarks This method should only be called once. Once called, property values should not be + changed. + + @param completion Optionally; the block invoked when the user profile change has been applied. + Invoked asynchronously on the main thread in the future. + */ +- (void)commitChangesWithCompletion:(nullable FIRUserProfileChangeCallback)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserInfo.h new file mode 100644 index 00000000..04eca495 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserInfo.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief Represents user data returned from an identity provider. + */ +NS_SWIFT_NAME(UserInfo) +@protocol FIRUserInfo + +/** @property providerID + @brief The provider identifier. + */ +@property(nonatomic, copy, readonly) NSString *providerID; + +/** @property uid + @brief The provider's user ID for the user. + */ +@property(nonatomic, copy, readonly) NSString *uid; + +/** @property displayName + @brief The name of the user. + */ +@property(nonatomic, copy, readonly, nullable) NSString *displayName; + +/** @property photoURL + @brief The URL of the user's profile photo. + */ +@property(nonatomic, copy, readonly, nullable) NSURL *photoURL; + +/** @property email + @brief The user's email address. + */ +@property(nonatomic, copy, readonly, nullable) NSString *email; + +/** @property phoneNumber + @brief A phone number associated with the user. + @remarks This property is only available for users authenticated via phone number auth. + */ +@property(nonatomic, readonly, nullable) NSString *phoneNumber; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserMetadata.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserMetadata.h new file mode 100644 index 00000000..3ceae38d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FIRUserMetadata.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRUserMetadata + @brief A data class representing the metadata corresponding to a Firebase user. + */ +NS_SWIFT_NAME(UserMetadata) +@interface FIRUserMetadata : NSObject + +/** @property lastSignInDate + @brief Stores the last sign in date for the corresponding Firebase user. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *lastSignInDate; + +/** @property creationDate + @brief Stores the creation date for the corresponding Firebase user. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *creationDate; + +/** @fn init + @brief This class should not be initialized manually, an instance of this class can be obtained + from a Firebase user object. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuth.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuth.h new file mode 100644 index 00000000..4f4d1ca1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuth.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRActionCodeSettings.h" +#import "FIRAdditionalUserInfo.h" +#import "FIRAuth.h" +#import "FIRAuthCredential.h" +#import "FIRAuthDataResult.h" +#import "FIRAuthErrors.h" +#import "FIRAuthTokenResult.h" +#import "FIREmailAuthProvider.h" +#import "FIRFacebookAuthProvider.h" +#import "FIRFederatedAuthProvider.h" +#import "FIRGameCenterAuthProvider.h" +#import "FIRGitHubAuthProvider.h" +#import "FIRGoogleAuthProvider.h" +#import "FIRMultiFactor.h" +#import "FIRMultiFactorAssertion.h" +#import "FIRMultiFactorInfo.h" +#import "FIRMultiFactorResolver.h" +#import "FIRMultiFactorSession.h" +#import "FIROAuthCredential.h" +#import "FIROAuthProvider.h" +#import "FIRTwitterAuthProvider.h" +#import "FIRUser.h" +#import "FIRUserInfo.h" +#import "FIRUserMetadata.h" +#import "FirebaseAuthVersion.h" + +#if TARGET_OS_IOS +#import "FIRAuthAPNSTokenType.h" +#import "FIRAuthSettings.h" +#import "FIRAuthUIDelegate.h" +#import "FIRPhoneAuthCredential.h" +#import "FIRPhoneAuthProvider.h" +#import "FIRPhoneMultiFactorAssertion.h" +#import "FIRPhoneMultiFactorGenerator.h" +#import "FIRPhoneMultiFactorInfo.h" +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuthVersion.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuthVersion.h new file mode 100644 index 00000000..7b4b94e9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuthVersion.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + Version number for FirebaseAuth. + */ +extern const double FirebaseAuthVersionNum; + +/** + Version string for FirebaseAuth. + */ +extern const char *const FirebaseAuthVersionStr; diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h new file mode 100644 index 00000000..ff7c05de --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief The protocol for permanant data storage. + */ +@protocol FIRAuthStorage + +/** @fn initWithService: + @brief Initialize a @c FIRAuthStorage instance. + @param service The name of the storage service to use. + @return An initialized @c FIRAuthStorage instance for the specified service. + */ +- (id)initWithService:(NSString *)service; + +/** @fn dataForKey:error: + @brief Gets the data for @c key in the storage. The key is set for the attribute + @c kSecAttrAccount of a generic password query. + @param key The key to use. + @param error The address to store any error that occurs during the process, if not NULL. + If the operation was successful, its content is set to @c nil . + @return The data stored in the storage for @c key, if any. + */ +- (nullable NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error; + +/** @fn setData:forKey:error: + @brief Sets the data for @c key in the storage. The key is set for the attribute + @c kSecAttrAccount of a generic password query. + @param data The data to store. + @param key The key to use. + @param error The address to store any error that occurs during the process, if not NULL. + @return Whether the operation succeeded or not. + */ +- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error; + +/** @fn removeDataForKey:error: + @brief Removes the data for @c key in the storage. The key is set for the attribute + @c kSecAttrAccount of a generic password query. + @param key The key to use. + @param error The address to store any error that occurs during the process, if not NULL. + @return Whether the operation succeeded or not. + */ +- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error; + +@end + +/** @class FIRAuthKeychain + @brief The utility class to manipulate data in iOS Keychain. + */ +@interface FIRAuthKeychainServices : NSObject + +/** @fn getItemWithQuery:error: + @brief Get the item from keychain by given query. + @param query The query to query the keychain. + @param outError The address to store any error that occurs during the process, if not nil. + @return The item of the given query. nil if not exsit. + */ +- (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn setItem:withQuery:error: + @brief Set the item into keychain with given query. + @param item The item to be added into keychain. + @param query The query to query the keychain. + @param outError The address to store any error that occurs during the process, if not nil. + @return Whether the operation succeed. + */ +- (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn getItemWithQuery:error: + @brief Remove the item with given queryfrom keychain. + @param query The query to query the keychain. + @param outError The address to store any error that occurs during the process, if not nil. + @return Whether the operation succeed. + */ +- (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.m new file mode 100644 index 00000000..aa1683b4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.m @@ -0,0 +1,323 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" + +#import + +#import "FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +/** @var kAccountPrefix + @brief The prefix string for keychain item account attribute before the key. + @remarks A number "1" is encoded in the prefix in case we need to upgrade the scheme in future. + */ +static NSString *const kAccountPrefix = @"firebase_auth_1_"; + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthKeychainServices { + /** @var _service + @brief The name of the keychain service. + */ + NSString *_service; + + /** @var _legacyItemDeletedForKey + @brief Indicates whether or not this class knows that the legacy item for a particular key has + been deleted. + @remarks This dictionary is to avoid unecessary keychain operations against legacy items. + */ + NSMutableDictionary *_legacyEntryDeletedForKey; +} + +- (id)initWithService:(NSString *)service { + self = [super init]; + if (self) { + _service = [service copy]; + _legacyEntryDeletedForKey = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (nullable NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error { + if (!key.length) { + [NSException raise:NSInvalidArgumentException format:@"%@", @"The key cannot be nil or empty."]; + return nil; + } + NSData *data = [self itemWithQuery:[self genericPasswordQueryWithKey:key] error:error]; + if (error && *error) { + return nil; + } + if (data) { + return data; + } + // Check for legacy form. + if (_legacyEntryDeletedForKey[key]) { + return nil; + } + data = [self itemWithQuery:[self legacyGenericPasswordQueryWithKey:key] error:error]; + if (error && *error) { + return nil; + } + if (!data) { + // Mark legacy data as non-existing so we don't have to query it again. + _legacyEntryDeletedForKey[key] = @YES; + return nil; + } + // Move the data to current form. + if (![self setData:data forKey:key error:error]) { + return nil; + } + [self deleteLegacyItemWithKey:key]; + return data; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error { + if (!key.length) { + [NSException raise:NSInvalidArgumentException format:@"%@", @"The key cannot be nil or empty."]; + return NO; + } + NSDictionary *attributes = @{ + (__bridge id)kSecValueData : data, + (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, + }; + return [self setItemWithQuery:[self genericPasswordQueryWithKey:key] + attributes:attributes + error:error]; +} + +- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error { + if (!key.length) { + [NSException raise:NSInvalidArgumentException format:@"%@", @"The key cannot be nil or empty."]; + return NO; + } + if (![self deleteItemWithQuery:[self genericPasswordQueryWithKey:key] error:error]) { + return NO; + } + // Legacy form item, if exists, also needs to be removed, otherwise it will be exposed when + // current form item is removed, leading to incorrect semantics. + [self deleteLegacyItemWithKey:key]; + return YES; +} + +#pragma mark - Private methods for non-sharing keychain operations + +- (nullable NSData *)itemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error { + NSMutableDictionary *returningQuery = [query mutableCopy]; + returningQuery[(__bridge id)kSecReturnData] = @YES; + returningQuery[(__bridge id)kSecReturnAttributes] = @YES; + // Using a match limit of 2 means that we can check whether there is more than one item. + // If we used a match limit of 1 we would never find out. + returningQuery[(__bridge id)kSecMatchLimit] = @2; + + CFArrayRef result = NULL; + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)returningQuery, (CFTypeRef *)&result); + + if (status == noErr && result != NULL) { + NSArray *items = (__bridge_transfer NSArray *)result; + if (items.count != 1) { + if (error) { + *error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching" status:status]; + } + return nil; + } + + if (error) { + *error = nil; + } + NSDictionary *item = items[0]; + return item[(__bridge id)kSecValueData]; + } + + if (status == errSecItemNotFound) { + if (error) { + *error = nil; + } + } else { + if (error) { + *error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching" status:status]; + } + } + return nil; +} + +- (BOOL)setItemWithQuery:(NSDictionary *)query + attributes:(NSDictionary *)attributes + error:(NSError **_Nullable)error { + NSMutableDictionary *combined = [attributes mutableCopy]; + [combined addEntriesFromDictionary:query]; + BOOL hasItem = NO; + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)combined, NULL); + + if (status == errSecDuplicateItem) { + hasItem = YES; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + + if (status == noErr) { + return YES; + } + if (error) { + NSString *function = hasItem ? @"SecItemUpdate" : @"SecItemAdd"; + *error = [FIRAuthErrorUtils keychainErrorWithFunction:function status:status]; + } + return NO; +} + +- (BOOL)deleteItemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + if (status == noErr || status == errSecItemNotFound) { + return YES; + } + if (error) { + *error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemDelete" status:status]; + } + return NO; +} + +/** @fn deleteLegacyItemsWithKey: + @brief Deletes legacy item from the keychain if it is not already known to be deleted. + @param key The key for the item. + */ +- (void)deleteLegacyItemWithKey:(NSString *)key { + if (_legacyEntryDeletedForKey[key]) { + return; + } + NSDictionary *query = [self legacyGenericPasswordQueryWithKey:key]; + SecItemDelete((__bridge CFDictionaryRef)query); + _legacyEntryDeletedForKey[key] = @YES; +} + +/** @fn genericPasswordQueryWithKey: + @brief Returns a keychain query of generic password to be used to manipulate key'ed value. + @param key The key for the value being manipulated, used as the account field in the query. + */ +- (NSDictionary *)genericPasswordQueryWithKey:(NSString *)key { + return @{ + (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrAccount : [kAccountPrefix stringByAppendingString:key], + (__bridge id)kSecAttrService : _service, + }; +} + +/** @fn legacyGenericPasswordQueryWithKey: + @brief Returns a keychain query of generic password without service field, which is used by + previous version of this class. + @param key The key for the value being manipulated, used as the account field in the query. + */ +- (NSDictionary *)legacyGenericPasswordQueryWithKey:(NSString *)key { + return @{ + (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrAccount : key, + }; +} + +#pragma mark - Private methods for shared keychain operations + +- (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *mutableQuery = [query mutableCopy]; + + mutableQuery[(__bridge id)kSecReturnData] = @YES; + mutableQuery[(__bridge id)kSecReturnAttributes] = @YES; + mutableQuery[(__bridge id)kSecMatchLimit] = @2; + + CFArrayRef result = NULL; + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)mutableQuery, (CFTypeRef *)&result); + + if (status == noErr && result != NULL) { + NSArray *items = (__bridge_transfer NSArray *)result; + if (items.count != 1) { + if (outError) { + *outError = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching" + status:status]; + } + return nil; + } + + if (outError) { + *outError = nil; + } + NSDictionary *item = items[0]; + return item[(__bridge id)kSecValueData]; + } + + if (status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + } else { + if (outError) { + *outError = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching" + status:status]; + } + } + return nil; +} + +- (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSData *existingItem = [self getItemWithQuery:query error:outError]; + if (outError && *outError) { + return NO; + } + + OSStatus status; + if (!existingItem) { + NSMutableDictionary *queryWithItem = [query mutableCopy]; + [queryWithItem setObject:item forKey:(__bridge id)kSecValueData]; + status = SecItemAdd((__bridge CFDictionaryRef)queryWithItem, NULL); + } else { + NSDictionary *attributes = @{(__bridge id)kSecValueData : item}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + + if (status == noErr) { + if (outError) { + *outError = nil; + } + return YES; + } + + NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd"; + if (outError) { + *outError = [FIRAuthErrorUtils keychainErrorWithFunction:function status:status]; + } + return NO; +} + +- (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + + if (status == noErr || status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + return YES; + } + + if (outError) { + *outError = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemDelete" status:status]; + } + return NO; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h new file mode 100644 index 00000000..dfd8aad9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthUserDefaults + @brief The utility class to storage data in NSUserDefaults. + */ +@interface FIRAuthUserDefaults : NSObject + +/** @fn clear + @brief Clears all data from the storage. + @remarks This method is only supposed to be called from tests. + */ +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.m new file mode 100644 index 00000000..b1094505 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const kPersistentDomainNamePrefix = @"com.google.Firebase.Auth."; + +@implementation FIRAuthUserDefaults { + /** @var _persistentDomainName + @brief The name of the persistent domain in user defaults. + */ + NSString *_persistentDomainName; + + /** @var _storage + @brief The backing NSUserDefaults storage for this instance. + */ + NSUserDefaults *_storage; +} + +- (instancetype)initWithService:(NSString *)service { + self = [super init]; + if (self) { + _persistentDomainName = [kPersistentDomainNamePrefix stringByAppendingString:service]; + _storage = [[NSUserDefaults alloc] init]; + } + return self; +} + +- (nullable NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error { + if (error) { + *error = nil; + } + NSDictionary *allData = [_storage persistentDomainForName:_persistentDomainName]; + return allData[key]; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error { + NSMutableDictionary *allData = + [([_storage persistentDomainForName:_persistentDomainName] ?: @{}) mutableCopy]; + allData[key] = data; + [_storage setPersistentDomain:allData forName:_persistentDomainName]; + return YES; +} + +- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error { + NSMutableDictionary *allData = + [[_storage persistentDomainForName:_persistentDomainName] mutableCopy]; + [allData removeObjectForKey:key]; + [_storage setPersistentDomain:allData forName:_persistentDomainName]; + return YES; +} + +- (void)clear { + [_storage setPersistentDomain:@{} forName:_persistentDomainName]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h new file mode 100644 index 00000000..b797199b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthAPNSToken + @brief A data structure for an APNs token. + */ +@interface FIRAuthAPNSToken : NSObject + +/** @property data + @brief The APNs token data. + */ +@property(nonatomic, strong, readonly) NSData *data; + +/** @property string + @brief The uppercase hexadecimal string form of the APNs token data. + */ +@property(nonatomic, strong, readonly) NSString *string; + +/** @property type + @brief The APNs token type. + */ +@property(nonatomic, assign, readonly) FIRAuthAPNSTokenType type; + +/** @fn initWithData:type: + @brief Initializes the instance. + @param data The APNs token data. + @param type The APNs token type. + @return The initialized instance. + */ +- (instancetype)initWithData:(NSData *)data + type:(FIRAuthAPNSTokenType)type NS_DESIGNATED_INITIALIZER; + +/** @fn init + @brief Call @c initWithData:type: to get an instance of this class. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.m new file mode 100644 index 00000000..1a976a0e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.m @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthAPNSToken { + /** @var _string + @brief The lazy-initialized string form of the token data. + */ + NSString *_string; +} + +- (instancetype)initWithData:(NSData *)data type:(FIRAuthAPNSTokenType)type { + self = [super init]; + if (self) { + _data = [data copy]; + _type = type; + } + return self; +} + +- (NSString *)string { + if (!_string) { + NSUInteger capacity = _data.length * 2; + NSMutableString *tokenString = [NSMutableString stringWithCapacity:capacity]; + const unsigned char *tokenData = _data.bytes; + for (int idx = 0; idx < _data.length; ++idx) { + [tokenString appendFormat:@"%02X", (int)tokenData[idx]]; + } + _string = tokenString; + } + return _string; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h new file mode 100644 index 00000000..5e2acfeb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import + +@class FIRAuthAPNSToken; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthAPNSTokenCallback + @brief The type of block to receive an APNs token. + @param token The APNs token if one is available. + @param error The error happened if any. + @remarks Both `token` and `error` being `nil` means the request timed-out. + */ +typedef void (^FIRAuthAPNSTokenCallback)(FIRAuthAPNSToken *_Nullable token, + NSError *_Nullable error); + +/** @class FIRAuthAPNSTokenManager + @brief A class to manage APNs token in memory. + */ +@interface FIRAuthAPNSTokenManager : NSObject + +/** @property token + @brief The APNs token, if one is available. + @remarks Setting a token with FIRAuthAPNSTokenTypeUnknown will automatically converts it to + a token with the automatically detected type. + */ +@property(nonatomic, strong, nullable) FIRAuthAPNSToken *token; + +/** @property timeout + @brief The timeout for registering for remote notification. + @remarks Only tests should access this property. + */ +@property(nonatomic, assign) NSTimeInterval timeout; + +/** @fn init + @brief Call @c initWithApplication: to initialize an instance of this class. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithApplication:bundle + @brief Initializes the instance. + @param application The @c UIApplication to request the token from. + @return The initialized instance. + */ +- (instancetype)initWithApplication:(UIApplication *)application NS_DESIGNATED_INITIALIZER; + +/** @fn getTokenWithCallback: + @brief Attempts to get the APNs token. + @param callback The block to be called either immediately or in future, either when a token + becomes available, or when timeout occurs, whichever happens earlier. + */ +- (void)getTokenWithCallback:(FIRAuthAPNSTokenCallback)callback; + +/** @fn cancelWithError: + @brief Cancels any pending `getTokenWithCallback:` request. + @param error The error to return. + */ +- (void)cancelWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.m new file mode 100644 index 00000000..967aace6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.m @@ -0,0 +1,250 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kRegistrationTimeout + @brief Timeout for registration for remote notification. + @remarks Once we start to handle `application:didFailToRegisterForRemoteNotificationsWithError:` + we probably don't have to use timeout at all. + */ +static const NSTimeInterval kRegistrationTimeout = 5; + +/** @var kLegacyRegistrationTimeout + @brief Timeout for registration for remote notification on iOS 7. + */ +static const NSTimeInterval kLegacyRegistrationTimeout = 30; + +@implementation FIRAuthAPNSTokenManager { + /** @var _application + @brief The @c UIApplication to request the token from. + */ + UIApplication *_application; + + /** @var _pendingCallbacks + @brief The list of all pending callbacks for the APNs token. + */ + NSMutableArray *_pendingCallbacks; +} + +- (instancetype)initWithApplication:(UIApplication *)application { + self = [super init]; + if (self) { + _application = application; + _timeout = [_application respondsToSelector:@selector(registerForRemoteNotifications)] + ? kRegistrationTimeout + : kLegacyRegistrationTimeout; + } + return self; +} + +- (void)getTokenWithCallback:(FIRAuthAPNSTokenCallback)callback { + if (_token) { + callback(_token, nil); + return; + } + if (_pendingCallbacks) { + [_pendingCallbacks addObject:callback]; + return; + } + _pendingCallbacks = + [[NSMutableArray alloc] initWithObjects:callback, nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self->_application respondsToSelector:@selector(registerForRemoteNotifications)]) { + [self->_application registerForRemoteNotifications]; + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if TARGET_OS_IOS + [self->_application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert]; +#endif // TARGET_OS_IOS +#pragma clang diagnostic pop + } + }); + NSArray *applicableCallbacks = _pendingCallbacks; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeout * NSEC_PER_SEC)), + FIRAuthGlobalWorkQueue(), ^{ + // Only cancel if the pending callbacks remain the same, i.e., not triggered yet. + if (applicableCallbacks == self->_pendingCallbacks) { + [self callBackWithToken:nil error:nil]; + } + }); +} + +- (void)setToken:(nullable FIRAuthAPNSToken *)token { + if (!token) { + _token = nil; + return; + } + if (token.type == FIRAuthAPNSTokenTypeUnknown) { + static FIRAuthAPNSTokenType detectedTokenType = FIRAuthAPNSTokenTypeUnknown; + if (detectedTokenType == FIRAuthAPNSTokenTypeUnknown) { + detectedTokenType = + [[self class] isProductionApp] ? FIRAuthAPNSTokenTypeProd : FIRAuthAPNSTokenTypeSandbox; + } + token = [[FIRAuthAPNSToken alloc] initWithData:token.data type:detectedTokenType]; + } + _token = token; + [self callBackWithToken:token error:nil]; +} + +- (void)cancelWithError:(NSError *)error { + [self callBackWithToken:nil error:error]; +} + +#pragma mark - Internal methods + +/** @fn callBack + @brief Calls back all pending callbacks with APNs token or error. + @param token The APNs token if one is available. + @param error The error occurred, if any. + */ +- (void)callBackWithToken:(nullable FIRAuthAPNSToken *)token error:(nullable NSError *)error { + if (!_pendingCallbacks) { + return; + } + NSArray *allCallbacks = _pendingCallbacks; + _pendingCallbacks = nil; + for (FIRAuthAPNSTokenCallback callback in allCallbacks) { + callback(token, error); + } +}; + +/** @fn isProductionApp + @brief Whether or not the app has production (versus sandbox) provisioning profile. + @remarks This method is adapted from @c FIRInstanceID . + */ ++ (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + + if ([GULAppEnvironmentUtil isSimulator]) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000006", @"Assuming prod APNs token type on simulator."); + return defaultAppTypeProd; + } + + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + if ([GULAppEnvironmentUtil isFromAppStore]) { + return defaultAppTypeProd; + } + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) { + // Distributed via TestFlight + return defaultAppTypeProd; + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000007", @"Error while reading embedded mobileprovision %@", + error); + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000008", @"Error while reading embedded mobileprovision %@", + error); + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@""]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000009", + @"Couldn't read plist fetched from embedded mobileprovision"); + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000010", @"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription); + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000011", + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:@"Entitlements.aps-environment"]; + FIRLogDebug(kFIRLoggerAuth, @"I-AUT000012", @"APNS Environment in profile: %@", apsEnvironment); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + FIRLogInfo(kFIRLoggerAuth, @"I-AUT000013", + @"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning profiles."); + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:@"development"]) { + return NO; + } + + return defaultAppTypeProd; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h new file mode 100644 index 00000000..ceb93e29 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthAppCredential + @brief A class represents a credential that proves the identity of the app. + */ +@interface FIRAuthAppCredential : NSObject + +/** @property receipt + @brief The server acknowledgement of receiving client's claim of identity. + */ +@property(nonatomic, strong, readonly) NSString *receipt; + +/** @property secret + @brief The secret that the client received from server via a trusted channel, if ever. + */ +@property(nonatomic, strong, readonly, nullable) NSString *secret; + +/** @fn initWithReceipt:secret: + @brief Initializes the instance. + @param receipt The server acknowledgement of receiving client's claim of identity. + @param secret The secret that the client received from server via a trusted channel, if ever. + @return The initialized instance. + */ +- (instancetype)initWithReceipt:(NSString *)receipt + secret:(nullable NSString *)secret NS_DESIGNATED_INITIALIZER; + +/** @fn init + @brief Call @c initWithReceipt:secret: to get an instance of this class. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.m new file mode 100644 index 00000000..7bf1021a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.m @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kReceiptKey + @brief The key used to encode the receipt property for NSSecureCoding. + */ +static NSString *const kReceiptKey = @"receipt"; + +/** @var kSecretKey + @brief The key used to encode the secret property for NSSecureCoding. + */ +static NSString *const kSecretKey = @"secret"; + +@implementation FIRAuthAppCredential + +- (instancetype)initWithReceipt:(NSString *)receipt secret:(nullable NSString *)secret { + self = [super init]; + if (self) { + _receipt = [receipt copy]; + _secret = [secret copy]; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *receipt = [aDecoder decodeObjectOfClass:[NSString class] forKey:kReceiptKey]; + if (!receipt) { + return nil; + } + NSString *secret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kSecretKey]; + return [self initWithReceipt:receipt secret:secret]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_receipt forKey:kReceiptKey]; + [aCoder encodeObject:_secret forKey:kSecretKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h new file mode 100644 index 00000000..a307d422 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h @@ -0,0 +1,90 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import + +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthAppCredentialCallback + @brief The type of block to receive an app crdential. + @param credential The best available app credential at the time. + */ +typedef void (^FIRAuthAppCredentialCallback)(FIRAuthAppCredential *credential); + +/** @class FIRAuthAppCredentialManager + @brief A class to manage app credentials backed by iOS Keychain. + */ +@interface FIRAuthAppCredentialManager : NSObject + +/** @property credential + @brief The full credential (which has a secret) to be used by the app, if one is available. + */ +@property(nonatomic, strong, readonly, nullable) FIRAuthAppCredential *credential; + +/** @property maximumNumberOfPendingReceipts + @brief The maximum (but not necessarily the minimum) number of pending receipts to be kept. + @remarks Only tests should access this property. + */ +@property(nonatomic, assign, readonly) NSUInteger maximumNumberOfPendingReceipts; + +/** @fn init + @brief Call @c initWithKeychain: to initialize an instance of this class. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithKeychain: + @brief Initializes the instance. + @param keychain The iOS Keychain storage to back up the app credential with. + @return The initialized instance. + */ +- (instancetype)initWithKeychain:(FIRAuthKeychainServices *)keychain NS_DESIGNATED_INITIALIZER; + +/** @fn didStartVerificationWithReceipt:timeout:callback: + @brief Notifies that the app verification process has started. + @param receipt The receipt for verification. + @param timeout The timeout value for how long the callback is waited to be called. + @param callback The block to be called in future either when the verification finishes, or + when timeout occurs, whichever happens earlier. + */ +- (void)didStartVerificationWithReceipt:(NSString *)receipt + timeout:(NSTimeInterval)timeout + callback:(FIRAuthAppCredentialCallback)callback; + +/** @fn canFinishVerificationWithReceipt: + @brief Attempts to finish verification. + @param receipt The receipt to match the original receipt obtained when verification started. + @param secret The secret to complete the verification. + @return Whether or not the receipt matches a pending verification, and finishes verification + if it does. + */ +- (BOOL)canFinishVerificationWithReceipt:(NSString *)receipt secret:(NSString *)secret; + +/** @fn clearCredential + @brief Clears the saved credential, to be used in the case that it is rejected by the server. + */ +- (void)clearCredential; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.m new file mode 100644 index 00000000..94ceaf11 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.m @@ -0,0 +1,175 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kKeychainDataKey + @brief The keychain key for the data. + */ +static NSString *const kKeychainDataKey = @"app_credentials"; + +/** @var kFullCredentialKey + @brief The data key for the full app credential. + */ +static NSString *const kFullCredentialKey = @"full_credential"; + +/** @var kPendingReceiptsKey + @brief The data key for the array of pending receipts. + */ +static NSString *const kPendingReceiptsKey = @"pending_receipts"; + +/** @var kMaximumNumberOfPendingReceipts + @brief The maximum number of partial credentials kept by this class. + */ +static const NSUInteger kMaximumNumberOfPendingReceipts = 32; + +@implementation FIRAuthAppCredentialManager { + /** @var _keychainServices + @brief The keychain for app credentials to load from and to save to. + */ + FIRAuthKeychainServices *_keychainServices; + + /** @var _pendingReceipts + @brief A list of pending receipts sorted in the order they were recorded. + */ + NSMutableArray *_pendingReceipts; + + /** @var _callbacksByReceipt + @brief A map from pending receipts to callbacks. + */ + NSMutableDictionary *_callbacksByReceipt; +} + +- (instancetype)initWithKeychain:(FIRAuthKeychainServices *)keychain { + self = [super init]; + if (self) { + _keychainServices = keychain; + // Load the credentials from keychain if possible. + NSError *error; + NSData *encodedData = [_keychainServices dataForKey:kKeychainDataKey error:&error]; + if (!error && encodedData) { +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = + [[NSKeyedUnarchiver alloc] initForReadingWithData:encodedData]; +#pragma clang diagnostic pop + FIRAuthAppCredential *credential = + [unarchiver decodeObjectOfClass:[FIRAuthAppCredential class] forKey:kFullCredentialKey]; + if ([credential isKindOfClass:[FIRAuthAppCredential class]]) { + _credential = credential; + } + NSSet *allowedClasses = + [NSSet setWithObjects:[NSArray class], [NSString class], nil]; + NSArray *pendingReceipts = [unarchiver decodeObjectOfClasses:allowedClasses + forKey:kPendingReceiptsKey]; + if ([pendingReceipts isKindOfClass:[NSArray class]]) { + _pendingReceipts = [pendingReceipts mutableCopy]; + } + } + if (!_pendingReceipts) { + _pendingReceipts = [[NSMutableArray alloc] init]; + } + _callbacksByReceipt = + [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (NSUInteger)maximumNumberOfPendingReceipts { + return kMaximumNumberOfPendingReceipts; +} + +- (void)didStartVerificationWithReceipt:(NSString *)receipt + timeout:(NSTimeInterval)timeout + callback:(FIRAuthAppCredentialCallback)callback { + [_pendingReceipts removeObject:receipt]; + if (_pendingReceipts.count >= kMaximumNumberOfPendingReceipts) { + [_pendingReceipts removeObjectAtIndex:0]; + } + [_pendingReceipts addObject:receipt]; + _callbacksByReceipt[receipt] = callback; + [self saveData]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)), + FIRAuthGlobalWorkQueue(), ^{ + [self callBackWithReceipt:receipt]; + }); +} + +- (BOOL)canFinishVerificationWithReceipt:(NSString *)receipt secret:(NSString *)secret { + if (![_pendingReceipts containsObject:receipt]) { + return NO; + } + [_pendingReceipts removeObject:receipt]; + _credential = [[FIRAuthAppCredential alloc] initWithReceipt:receipt secret:secret]; + [self saveData]; + [self callBackWithReceipt:receipt]; + return YES; +} + +- (void)clearCredential { + _credential = nil; + [self saveData]; +} + +#pragma mark - Internal methods + +/** @fn saveData + @brief Save the data in memory to the keychain ignoring any errors. + */ +- (void)saveData { + NSMutableData *archiveData = [NSMutableData data]; +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData]; +#pragma clang diagnostic pop + [archiver encodeObject:_credential forKey:kFullCredentialKey]; + [archiver encodeObject:_pendingReceipts forKey:kPendingReceiptsKey]; + [archiver finishEncoding]; + [_keychainServices setData:archiveData forKey:kKeychainDataKey error:NULL]; +} + +/** @fn callBackWithReceipt: + @brief Calls the saved callback for the specifc receipt. + @param receipt The receipt associated with the callback. + */ +- (void)callBackWithReceipt:(NSString *)receipt { + FIRAuthAppCredentialCallback callback = _callbacksByReceipt[receipt]; + if (!callback) { + return; + } + [_callbacksByReceipt removeObjectForKey:receipt]; + if (_credential) { + callback(_credential); + } else { + callback([[FIRAuthAppCredential alloc] initWithReceipt:receipt secret:nil]); + } +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h new file mode 100644 index 00000000..3de2e32e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h @@ -0,0 +1,76 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import + +@class FIRAuthAppCredentialManager; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRAuthNotificationForwardingCallback + @brief The type of block to receive whether or not remote notifications are being forwarded. + @param isNotificationBeingForwarded Whether or not remote notifications are being forwarded. + */ +typedef void (^FIRAuthNotificationForwardingCallback)(BOOL isNotificationBeingForwarded); + +/** @class FIRAuthNotificationManager + */ +@interface FIRAuthNotificationManager : NSObject + +/** @property timeout + @brief The timeout for checking for notification forwarding. + @remarks Only tests should access this property. + */ +@property(nonatomic, assign) NSTimeInterval timeout; + +/** @fn initWithApplication:appCredentialManager: + @brief Initializes the instance. + @param application The application. + @param appCredentialManager The object to handle app credentials delivered via notification. + @return The initialized instance. + */ +- (instancetype)initWithApplication:(UIApplication *)application + appCredentialManager:(FIRAuthAppCredentialManager *)appCredentialManager + NS_DESIGNATED_INITIALIZER; + +/** @fn init + @brief please use initWithAppCredentialManager: instead. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn checkNotificationForwardingWithCallback: + @brief Checks whether or not remote notifications are being forwarded to this class. + @param callback The block to be called either immediately or in future once a result + is available. + */ +- (void)checkNotificationForwardingWithCallback:(FIRAuthNotificationForwardingCallback)callback; + +/** @fn canHandleNotification: + @brief Attempts to handle the remote notification. + @param notification The notification in question. + @return Whether or the notification has been handled. + */ +- (BOOL)canHandleNotification:(NSDictionary *)notification; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.m new file mode 100644 index 00000000..45844149 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.m @@ -0,0 +1,188 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h" +#import "FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kNotificationKey + @brief The key to locate payload data in the remote notification. + */ +static NSString *const kNotificationDataKey = @"com.google.firebase.auth"; + +/** @var kNotificationReceiptKey + @brief The key for the receipt in the remote notification payload data. + */ +static NSString *const kNotificationReceiptKey = @"receipt"; + +/** @var kNotificationSecretKey + @brief The key for the secret in the remote notification payload data. + */ +static NSString *const kNotificationSecretKey = @"secret"; + +/** @var kNotificationProberKey + @brief The key for marking the prober in the remote notification payload data. + */ +static NSString *const kNotificationProberKey = @"warning"; + +/** @var kProbingTimeout + @brief Timeout for probing whether the app delegate forwards the remote notification to us. + */ +static const NSTimeInterval kProbingTimeout = 1; + +@implementation FIRAuthNotificationManager { + /** @var _application + @brief The application. + */ + UIApplication *_application; + + /** @var _appCredentialManager + @brief The object to handle app credentials delivered via notification. + */ + FIRAuthAppCredentialManager *_appCredentialManager; + + /** @var _hasCheckedNotificationForwarding + @brief Whether notification forwarding has been checked or not. + */ + BOOL _hasCheckedNotificationForwarding; + + /** @var _isNotificationBeingForwarded + @brief Whether or not notification is being forwarded + */ + BOOL _isNotificationBeingForwarded; + + /** @var _pendingCallbacks + @brief All pending callbacks while a check is being performed. + */ + NSMutableArray *_pendingCallbacks; +} + +- (instancetype)initWithApplication:(UIApplication *)application + appCredentialManager:(FIRAuthAppCredentialManager *)appCredentialManager { + self = [super init]; + if (self) { + _application = application; + _appCredentialManager = appCredentialManager; + _timeout = kProbingTimeout; + } + return self; +} + +- (void)checkNotificationForwardingWithCallback:(FIRAuthNotificationForwardingCallback)callback { + if (_pendingCallbacks) { + [_pendingCallbacks addObject:callback]; + return; + } + if (_hasCheckedNotificationForwarding) { + callback(_isNotificationBeingForwarded); + return; + } + _hasCheckedNotificationForwarding = YES; + _pendingCallbacks = + [[NSMutableArray alloc] initWithObjects:callback, nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSDictionary *proberNotification = @{ + kNotificationDataKey : @{ + kNotificationProberKey : @"This fake notification should be forwarded to Firebase Auth." + } + }; + if ([self->_application.delegate + respondsToSelector:@selector(application: + didReceiveRemoteNotification:fetchCompletionHandler:)]) { + [self->_application.delegate application:self->_application + didReceiveRemoteNotification:proberNotification + fetchCompletionHandler:^(UIBackgroundFetchResult result){ + }]; +#if !TARGET_OS_TV + } else if ([self->_application.delegate + respondsToSelector:@selector(application:didReceiveRemoteNotification:)]) { +// iOS 10 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [self->_application.delegate application:self->_application + didReceiveRemoteNotification:proberNotification]; +#pragma clang diagnostic pop +#endif + } else { + FIRLogWarning(kFIRLoggerAuth, @"I-AUT000015", + @"The UIApplicationDelegate must handle remote notification for phone number " + @"authentication to work."); + } + }); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeout * NSEC_PER_SEC)), + FIRAuthGlobalWorkQueue(), ^{ + [self callBack]; + }); +} + +- (BOOL)canHandleNotification:(NSDictionary *)notification { + NSDictionary *data = notification[kNotificationDataKey]; + if ([data isKindOfClass:[NSString class]]) { + // Deserialize in case the data is a JSON string. + NSData *JSONData = [((NSString *)data) dataUsingEncoding:NSUTF8StringEncoding]; + data = [NSJSONSerialization JSONObjectWithData:JSONData options:0 error:NULL]; + } + if (![data isKindOfClass:[NSDictionary class]]) { + return NO; + } + if (data[kNotificationProberKey]) { + if (!_pendingCallbacks) { + // The prober notification probably comes from another instance, so pass it along. + return NO; + } + _isNotificationBeingForwarded = YES; + [self callBack]; + return YES; + } + NSString *receipt = data[kNotificationReceiptKey]; + if (![receipt isKindOfClass:[NSString class]]) { + return NO; + } + NSString *secret = data[kNotificationSecretKey]; + if (![receipt isKindOfClass:[NSString class]]) { + return NO; + } + return [_appCredentialManager canFinishVerificationWithReceipt:receipt secret:secret]; +} + +#pragma mark - Internal methods + +/** @fn callBack + @brief Calls back all pending callbacks with the result of notification forwarding check. + */ +- (void)callBack { + if (!_pendingCallbacks) { + return; + } + NSArray *allCallbacks = _pendingCallbacks; + _pendingCallbacks = nil; + for (FIRAuthNotificationForwardingCallback callback in allCallbacks) { + callback(_isNotificationBeingForwarded); + } +}; + +@end +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h new file mode 100644 index 00000000..ebb10ec5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h @@ -0,0 +1,99 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h" +#import "FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthStoredUserManager : NSObject + +/** @property keychain + @brief The mediator object to access to the system Keychain services. + */ +@property(readonly, nonatomic, strong) FIRAuthKeychainServices *keychainServices; + +/** @property userDefaults + @brief The mediator object to access to the system User Defaults services. + */ +@property(readonly, nonatomic, strong) FIRAuthUserDefaults *userDefaults; + +/** @fn init + @brief The default initializer is disabled. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithServiceName: + @brief The designated initializer. + @param serviceName The service name to initialize with. + */ +- (instancetype)initWithServiceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER; + +/** @fn getStoredUserAccessGroupWithError: + @brief Get the user access group stored locally. + @param outError Return value for any error which occurs. + */ +- (NSString *_Nullable)getStoredUserAccessGroupWithError:(NSError *_Nullable *_Nullable)outError; + +/** @fn setStoredUserAccessGroup:error: + @brief The setter of the user access group stored locally. + @param accessGroup The access group to be set. + @param outError Return value for any error which occurs. + */ +- (BOOL)setStoredUserAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn getStoredUserForAccessGroup:projectID:error: + @brief The getter of the user stored locally. + @param accessGroup The access group to retrieve the user from. + @param projectIdentifier An identifier of the project that the user associates with. Currently, + we use API KEY. + @param outError Return value for any error which occurs. + */ +- (FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn setStoredUser:forAccessGroup:projectID:error: + @brief The setter of the user stored locally. + @param user The user to be stored. + @param accessGroup The access group to store the user in. + @param projectIdentifier An identifier of the project that the user associates with. Currently, + we use API KEY. + @param outError Return value for any error which occurs. + */ +- (BOOL)setStoredUser:(FIRUser *)user + forAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError; + +/** @fn removeStoredUserForAccessGroup:projectID:error: + @brief Remove the user that stored locally. + @param accessGroup The access group to remove the user from. + @param projectIdentifier An identifier of the project that the user associates with. Currently, + we use API KEY. + @param outError Return value for any error which occurs. + */ +- (BOOL)removeStoredUserForAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.m new file mode 100644 index 00000000..0eeb3e81 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.m @@ -0,0 +1,133 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h" + +/** @var kUserAccessGroupKey + @brief Key of user access group stored in user defaults. Used for retrieve the user access + group at launch. + */ +static NSString *kStoredUserAccessGroupKey = @"firebase_auth_stored_user_access_group"; + +/** @var kSharedKeychainAccountValue + @brief Default value for kSecAttrAccount of shared keychain items. + */ +static NSString *kSharedKeychainAccountValue = @"firebase_auth_firebase_user"; + +/** @var kStoredUserCoderKey + @brief The key to encode and decode the stored user. + */ +static NSString *kStoredUserCoderKey = @"firebase_auth_stored_user_coder_key"; + +@implementation FIRAuthStoredUserManager + +#pragma mark - Initializers + +- (instancetype)initWithServiceName:(NSString *)serviceName { + self = [super init]; + if (self) { + _keychainServices = [[FIRAuthKeychainServices alloc] initWithService:serviceName]; + _userDefaults = [[FIRAuthUserDefaults alloc] initWithService:serviceName]; + } + return self; +} + +#pragma mark - User Access Group + +- (NSString *_Nullable)getStoredUserAccessGroupWithError:(NSError *_Nullable *_Nullable)outError { + NSData *data = [self.userDefaults dataForKey:kStoredUserAccessGroupKey error:outError]; + if (data) { + NSString *userAccessGroup = [NSString stringWithUTF8String:data.bytes]; + return userAccessGroup; + } else { + return nil; + } +} + +- (BOOL)setStoredUserAccessGroup:(NSString *_Nullable)accessGroup + error:(NSError *_Nullable *_Nullable)outError { + NSData *data = [accessGroup dataUsingEncoding:NSUTF8StringEncoding]; + if (!data) { + return [self.userDefaults removeDataForKey:kStoredUserAccessGroupKey error:outError]; + } else { + return [self.userDefaults setData:data forKey:kStoredUserAccessGroupKey error:outError]; + } +} + +#pragma mark - User for Access Group + +- (FIRUser *)getStoredUserForAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + + query[(__bridge id)kSecAttrAccessGroup] = accessGroup; + query[(__bridge id)kSecAttrService] = projectIdentifier; + query[(__bridge id)kSecAttrAccount] = kSharedKeychainAccountValue; + + NSData *data = [self.keychainServices getItemWithQuery:query error:outError]; +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + FIRUser *user = [unarchiver decodeObjectOfClass:[FIRUser class] forKey:kStoredUserCoderKey]; + + return user; +} + +- (BOOL)setStoredUser:(FIRUser *)user + forAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + query[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + query[(__bridge id)kSecAttrAccessGroup] = accessGroup; + query[(__bridge id)kSecAttrService] = projectIdentifier; + query[(__bridge id)kSecAttrAccount] = kSharedKeychainAccountValue; + + NSMutableData *data = [NSMutableData data]; +// iOS 12 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + [archiver encodeObject:user forKey:kStoredUserCoderKey]; + [archiver finishEncoding]; + + return [self.keychainServices setItem:data withQuery:query error:outError]; +} + +- (BOOL)removeStoredUserForAccessGroup:(NSString *)accessGroup + projectIdentifier:(NSString *)projectIdentifier + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + query[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + query[(__bridge id)kSecAttrAccessGroup] = accessGroup; + query[(__bridge id)kSecAttrService] = projectIdentifier; + query[(__bridge id)kSecAttrAccount] = kSharedKeychainAccountValue; + + return [self.keychainServices removeItemWithQuery:query error:outError]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h new file mode 100644 index 00000000..ba03b7dd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthRequestConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRFetchAccessTokenCallback + @brief The callback used to return the value of attempting to fetch an access token. + + In the event the operation was successful @c token will be set and @c error will be @c nil. + In the event of failure @c token will be @c nil and @c error will be set. + @c tokenUpdated indicates whether either the access or the refresh token has been updated. + + The token returned should be considered ephemeral and not cached. It should be used immediately + and discarded. All operations that need this token should call fetchAccessToken and do their + work from the callback. + */ +typedef void (^FIRFetchAccessTokenCallback)(NSString *_Nullable token, + NSError *_Nullable error, + BOOL tokenUpdated); + +/** @class FIRSecureTokenService + @brief Provides services for token exchanges and refreshes. + */ +@interface FIRSecureTokenService : NSObject + +/** @property requestConfiguration + @brief The configuration for making requests to server. + */ +@property(nonatomic, strong) FIRAuthRequestConfiguration *requestConfiguration; + +/** @property rawAccessToken + @brief The cached access token. + @remarks This method is specifically for providing the access token to internal clients during + deserialization and sign-in events, and should not be used to retrieve the access token by + anyone else. + */ +@property(nonatomic, copy, readonly) NSString *rawAccessToken; + +/** @property refreshToken + @brief The refresh token for the user, or @c nil if the user has yet completed sign-in flow. + @remarks This property needs to be set manually after the instance is decoded from archive. + */ +@property(nonatomic, copy, readonly, nullable) NSString *refreshToken; + +/** @property accessTokenExpirationDate + @brief The expiration date of the cached access token. + */ +@property(nonatomic, copy, readonly, nullable) NSDate *accessTokenExpirationDate; + +/** @fn initWithRequestConfiguration:authorizationCode: + @brief Creates a @c FIRSecureTokenService with an authroization code. + @param requestConfiguration The configuration for making requests to server. + @param authorizationCode An authorization code which needs to be exchanged for STS tokens. + */ +- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + authorizationCode:(NSString *)authorizationCode; + +/** @fn initWithRequestConfiguration:accessToken:accessTokenExpirationDate:refreshToken + @brief Creates a @c FIRSecureTokenService with access and refresh tokens. + @param requestConfiguration The configuration for making requests to server. + @param accessToken The STS access token. + @param accessTokenExpirationDate The approximate expiration date of the access token. + @param refreshToken The STS refresh token. + */ +- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + accessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(NSString *)refreshToken; + +/** @fn fetchAccessTokenForcingRefresh:callback: + @brief Fetch a fresh ephemeral access token for the ID associated with this instance. The token + received in the callback should be considered short lived and not cached. + @param forceRefresh Forces the token to be refreshed. + @param callback Callback block that will be called to return either the token or an error. + Invoked asyncronously on the auth global work queue in the future. + */ +- (void)fetchAccessTokenForcingRefresh:(BOOL)forceRefresh + callback:(FIRFetchAccessTokenCallback)callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.m new file mode 100644 index 00000000..fb10cd68 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/SystemService/FIRSecureTokenService.m @@ -0,0 +1,208 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h" + +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kAPIKeyCodingKey + @brief The key used to encode the APIKey for NSSecureCoding. + */ +static NSString *const kAPIKeyCodingKey = @"APIKey"; + +/** @var kRefreshTokenKey + @brief The key used to encode the refresh token for NSSecureCoding. + */ +static NSString *const kRefreshTokenKey = @"refreshToken"; + +/** @var kAccessTokenKey + @brief The key used to encode the access token for NSSecureCoding. + */ +static NSString *const kAccessTokenKey = @"accessToken"; + +/** @var kAccessTokenExpirationDateKey + @brief The key used to encode the access token expiration date for NSSecureCoding. + */ +static NSString *const kAccessTokenExpirationDateKey = @"accessTokenExpirationDate"; + +/** @var kFiveMinutes + @brief Five minutes (in seconds.) + */ +static const NSTimeInterval kFiveMinutes = 5 * 60; + +@interface FIRSecureTokenService () +- (instancetype)init NS_DESIGNATED_INITIALIZER; +@end + +@implementation FIRSecureTokenService { + /** @var _taskQueue + @brief Used to serialize all requests for access tokens. + */ + FIRAuthSerialTaskQueue *_taskQueue; + + /** @var _authorizationCode + @brief An authorization code which needs to be exchanged for Secure Token Service tokens. + */ + NSString *_Nullable _authorizationCode; + + /** @var _accessToken + @brief The currently cached access token. Or |nil| if no token is currently cached. + */ + NSString *_Nullable _accessToken; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _taskQueue = [[FIRAuthSerialTaskQueue alloc] init]; + } + return self; +} + +- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + authorizationCode:(NSString *)authorizationCode { + self = [self init]; + if (self) { + _requestConfiguration = requestConfiguration; + _authorizationCode = [authorizationCode copy]; + } + return self; +} + +- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + accessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(NSString *)refreshToken { + self = [self init]; + if (self) { + _requestConfiguration = requestConfiguration; + _accessToken = [accessToken copy]; + _accessTokenExpirationDate = [accessTokenExpirationDate copy]; + _refreshToken = [refreshToken copy]; + } + return self; +} + +- (void)fetchAccessTokenForcingRefresh:(BOOL)forceRefresh + callback:(FIRFetchAccessTokenCallback)callback { + [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock complete) { + if (!forceRefresh && [self hasValidAccessToken]) { + complete(); + callback(self->_accessToken, nil, NO); + } else { + [self requestAccessToken:^(NSString *_Nullable token, NSError *_Nullable error, + BOOL tokenUpdated) { + complete(); + callback(token, error, tokenUpdated); + }]; + } + }]; +} + +- (NSString *)rawAccessToken { + return _accessToken; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey]; + NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAccessTokenKey]; + NSDate *accessTokenExpirationDate = [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kAccessTokenExpirationDateKey]; + if (!refreshToken) { + return nil; + } + self = [self init]; + if (self) { + _refreshToken = refreshToken; + _accessToken = accessToken; + _accessTokenExpirationDate = accessTokenExpirationDate; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + // The API key is encoded even it is not used in decoding to be compatible with previous versions + // of the library. + [aCoder encodeObject:_requestConfiguration.APIKey forKey:kAPIKeyCodingKey]; + // Authorization code is not encoded because it is not long-lived. + [aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey]; + [aCoder encodeObject:_accessToken forKey:kAccessTokenKey]; + [aCoder encodeObject:_accessTokenExpirationDate forKey:kAccessTokenExpirationDateKey]; +} + +#pragma mark - Private methods + +/** @fn requestAccessToken: + @brief Makes a request to STS for an access token. + @details This handles both the case that the token has not been granted yet and that it just + needs to be refreshed. The caller is responsible for making sure that this is occurring in + a @c _taskQueue task. + @param callback Called when the fetch is complete. Invoked asynchronously on the main thread in + the future. + @remarks Because this method is guaranteed to only be called from tasks enqueued in + @c _taskQueue, we do not need any @synchronized guards around access to _accessToken/etc. + since only one of those tasks is ever running at a time, and those tasks are the only + access to and mutation of these instance variables. + */ +- (void)requestAccessToken:(FIRFetchAccessTokenCallback)callback { + FIRSecureTokenRequest *request; + if (_refreshToken.length) { + request = [FIRSecureTokenRequest refreshRequestWithRefreshToken:_refreshToken + requestConfiguration:_requestConfiguration]; + } else { + request = [FIRSecureTokenRequest authCodeRequestWithCode:_authorizationCode + requestConfiguration:_requestConfiguration]; + } + [FIRAuthBackend + secureToken:request + callback:^(FIRSecureTokenResponse *_Nullable response, NSError *_Nullable error) { + BOOL tokenUpdated = NO; + NSString *newAccessToken = response.accessToken; + if (newAccessToken.length && ![newAccessToken isEqualToString:self->_accessToken]) { + self->_accessToken = [newAccessToken copy]; + self->_accessTokenExpirationDate = response.approximateExpirationDate; + tokenUpdated = YES; + } + NSString *newRefreshToken = response.refreshToken; + if (newRefreshToken.length && ![newRefreshToken isEqualToString:self->_refreshToken]) { + self->_refreshToken = [newRefreshToken copy]; + tokenUpdated = YES; + } + callback(newAccessToken, error, tokenUpdated); + }]; +} + +- (BOOL)hasValidAccessToken { + return _accessToken && [_accessTokenExpirationDate timeIntervalSinceNow] > kFiveMinutes; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo.m new file mode 100644 index 00000000..52f56c4f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo.m @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" +#import "FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAdditionalUserInfo + +/** @var kProviderIDCodingKey + @brief The key used to encode the providerID property for NSSecureCoding. + */ +static NSString *const kProviderIDCodingKey = @"providerID"; + +/** @var kProfileCodingKey + @brief The key used to encode the profile property for NSSecureCoding. + */ +static NSString *const kProfileCodingKey = @"profile"; + +/** @var kUsernameCodingKey + @brief The key used to encode the username property for NSSecureCoding. + */ +static NSString *const kUsernameCodingKey = @"username"; + +/** @var kNewUserKey + @brief The key used to encode the newUser property for NSSecureCoding. + */ +static NSString *const kNewUserKey = @"newUser"; + ++ (nullable instancetype)userInfoWithVerifyAssertionResponse: + (FIRVerifyAssertionResponse *)verifyAssertionResponse { + return [[self alloc] initWithProviderID:verifyAssertionResponse.providerID + profile:verifyAssertionResponse.profile + username:verifyAssertionResponse.username + isNewUser:verifyAssertionResponse.isNewUser]; +} + +- (nullable instancetype)initWithProviderID:(nullable NSString *)providerID + profile:(nullable NSDictionary *)profile + username:(nullable NSString *)username + isNewUser:(BOOL)isNewUser { + self = [super init]; + if (self) { + _providerID = [providerID copy]; + if (profile) { + _profile = [[NSDictionary alloc] initWithDictionary:profile copyItems:YES]; + } + _username = [username copy]; + _newUser = isNewUser; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *providerID = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kProviderIDCodingKey]; + NSDictionary *profile = [aDecoder decodeObjectOfClass:[NSDictionary class] + forKey:kProfileCodingKey]; + NSString *username = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUsernameCodingKey]; + NSNumber *isNewUser = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kNewUserKey]; + + return [self initWithProviderID:providerID + profile:profile + username:username + isNewUser:isNewUser.boolValue]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_providerID forKey:kProviderIDCodingKey]; + [aCoder encodeObject:_profile forKey:kProfileCodingKey]; + [aCoder encodeObject:_username forKey:kUsernameCodingKey]; + [aCoder encodeObject:[NSNumber numberWithBool:_newUser] forKey:kNewUserKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h new file mode 100644 index 00000000..485a883d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAdditionalUserInfo () + +/** @fn userInfoWithVerifyAssertionResponse: + @brief A convenience factory method for constructing a @c FIRAdditionalUserInfo instance from + data returned by the verifyAssertion endpoint. + @param verifyAssertionResponse Data returned by the verifyAssertion endpoint. + @return A new instance of @c FIRAdditionalUserInfo using data from the verifyAssertion endpoint. + */ ++ (nullable instancetype)userInfoWithVerifyAssertionResponse: + (FIRVerifyAssertionResponse *)verifyAssertionResponse; + +/** @fn initWithProviderID:profile:username: + @brief Designated initializer. + @param providerID The provider identifier. + @param profile Dictionary containing the additional IdP specific information. + @param username The name of the user. + @param isNewUser Indicates whether or not the current user was signed in for the first time. + */ +- (nullable instancetype)initWithProviderID:(nullable NSString *)providerID + profile:(nullable NSDictionary *)profile + username:(nullable NSString *)username + isNewUser:(BOOL)isNewUser NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser.m new file mode 100644 index 00000000..a97acc9f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser.m @@ -0,0 +1,1604 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthOperationType.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h" +#import "FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h" +#import "FirebaseAuth/Sources/Auth/FIRAuth_Internal.h" +#import "FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h" +#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h" +#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h" +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h" +#import "FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h" +#import "FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h" +#import "FirebaseAuth/Sources/User/FIRUserInfoImpl.h" +#import "FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h" +#import "FirebaseAuth/Sources/User/FIRUser_Internal.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h" + +#if TARGET_OS_IOS +#import + +#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** @var kUserIDCodingKey + @brief The key used to encode the user ID for NSSecureCoding. + */ +static NSString *const kUserIDCodingKey = @"userID"; + +/** @var kHasEmailPasswordCredentialCodingKey + @brief The key used to encode the hasEmailPasswordCredential property for NSSecureCoding. + */ +static NSString *const kHasEmailPasswordCredentialCodingKey = @"hasEmailPassword"; + +/** @var kAnonymousCodingKey + @brief The key used to encode the anonymous property for NSSecureCoding. + */ +static NSString *const kAnonymousCodingKey = @"anonymous"; + +/** @var kEmailCodingKey + @brief The key used to encode the email property for NSSecureCoding. + */ +static NSString *const kEmailCodingKey = @"email"; + +/** @var kPhoneNumberCodingKey + @brief The key used to encode the phoneNumber property for NSSecureCoding. + */ +static NSString *const kPhoneNumberCodingKey = @"phoneNumber"; + +/** @var kEmailVerifiedCodingKey + @brief The key used to encode the isEmailVerified property for NSSecureCoding. + */ +static NSString *const kEmailVerifiedCodingKey = @"emailVerified"; + +/** @var kDisplayNameCodingKey + @brief The key used to encode the displayName property for NSSecureCoding. + */ +static NSString *const kDisplayNameCodingKey = @"displayName"; + +/** @var kPhotoURLCodingKey + @brief The key used to encode the photoURL property for NSSecureCoding. + */ +static NSString *const kPhotoURLCodingKey = @"photoURL"; + +/** @var kProviderDataKey + @brief The key used to encode the providerData instance variable for NSSecureCoding. + */ +static NSString *const kProviderDataKey = @"providerData"; + +/** @var kAPIKeyCodingKey + @brief The key used to encode the APIKey instance variable for NSSecureCoding. + */ +static NSString *const kAPIKeyCodingKey = @"APIKey"; + +/** @var kTokenServiceCodingKey + @brief The key used to encode the tokenService instance variable for NSSecureCoding. + */ +static NSString *const kTokenServiceCodingKey = @"tokenService"; + +/** @var kMetadataCodingKey + @brief The key used to encode the metadata instance variable for NSSecureCoding. + */ +static NSString *const kMetadataCodingKey = @"metadata"; + +static NSString *const kMultiFactorCodingKey = @"multiFactor"; + +/** @var kMissingUsersErrorMessage + @brief The error message when there is no users array in the getAccountInfo response. + */ +static NSString *const kMissingUsersErrorMessage = @"users"; + +/** @typedef CallbackWithError + @brief The type for a callback block that only takes an error parameter. + */ +typedef void (^CallbackWithError)(NSError *_Nullable); + +/** @typedef CallbackWithUserAndError + @brief The type for a callback block that takes a user parameter and an error parameter. + */ +typedef void (^CallbackWithUserAndError)(FIRUser *_Nullable, NSError *_Nullable); + +/** @typedef CallbackWithUserAndError + @brief The type for a callback block that takes a user parameter and an error parameter. + */ +typedef void (^CallbackWithAuthDataResultAndError)(FIRAuthDataResult *_Nullable, + NSError *_Nullable); + +/** @var kMissingPasswordReason + @brief The reason why the @c FIRAuthErrorCodeWeakPassword error is thrown. + @remarks This error message will be localized in the future. + */ +static NSString *const kMissingPasswordReason = @"Missing Password"; + +/** @fn callInMainThreadWithError + @brief Calls a callback in main thread with error. + @param callback The callback to be called in main thread. + @param error The error to pass to callback. + */ +static void callInMainThreadWithError(_Nullable CallbackWithError callback, + NSError *_Nullable error) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(error); + }); + } +} + +/** @fn callInMainThreadWithUserAndError + @brief Calls a callback in main thread with user and error. + @param callback The callback to be called in main thread. + @param user The user to pass to callback if there is no error. + @param error The error to pass to callback. + */ +static void callInMainThreadWithUserAndError(_Nullable CallbackWithUserAndError callback, + FIRUser *_Nonnull user, + NSError *_Nullable error) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(error ? nil : user, error); + }); + } +} + +/** @fn callInMainThreadWithUserAndError + @brief Calls a callback in main thread with user and error. + @param callback The callback to be called in main thread. + @param result The result to pass to callback if there is no error. + @param error The error to pass to callback. + */ +static void callInMainThreadWithAuthDataResultAndError( + _Nullable CallbackWithAuthDataResultAndError callback, + FIRAuthDataResult *_Nullable result, + NSError *_Nullable error) { + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(result, error); + }); + } +} + +@interface FIRUserProfileChangeRequest () + +/** @fn initWithUser: + @brief Designated initializer. + @param user The user for which we are updating profile information. + */ +- (nullable instancetype)initWithUser:(FIRUser *)user NS_DESIGNATED_INITIALIZER; + +@end + +@interface FIRUser () + +/** @property anonymous + @brief Whether the current user is anonymous. + */ +@property(nonatomic, readwrite) BOOL anonymous; + +@end + +@implementation FIRUser { + /** @var _hasEmailPasswordCredential + @brief Whether or not the user can be authenticated by using Firebase email and password. + */ + BOOL _hasEmailPasswordCredential; + + /** @var _providerData + @brief Provider specific user data. + */ + NSDictionary *_providerData; + + /** @var _taskQueue + @brief Used to serialize the update profile calls. + */ + FIRAuthSerialTaskQueue *_taskQueue; + + /** @var _tokenService + @brief A secure token service associated with this user. For performing token exchanges and + refreshing access tokens. + */ + FIRSecureTokenService *_tokenService; +} + +#pragma mark - Properties + +// Explicitly @synthesize because these properties are defined in FIRUserInfo protocol. +@synthesize uid = _userID; +@synthesize displayName = _displayName; +@synthesize photoURL = _photoURL; +@synthesize email = _email; +@synthesize phoneNumber = _phoneNumber; + +#pragma mark - + ++ (void)retrieveUserWithAuth:(FIRAuth *)auth + accessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(nullable NSString *)refreshToken + anonymous:(BOOL)anonymous + callback:(FIRRetrieveUserCallback)callback { + FIRSecureTokenService *tokenService = + [[FIRSecureTokenService alloc] initWithRequestConfiguration:auth.requestConfiguration + accessToken:accessToken + accessTokenExpirationDate:accessTokenExpirationDate + refreshToken:refreshToken]; + FIRUser *user = [[self alloc] initWithTokenService:tokenService]; + user.auth = auth; + user.requestConfiguration = auth.requestConfiguration; + [user internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + callback(nil, error); + return; + } + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken + requestConfiguration:auth.requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + // No need to sign out user here for errors because the user hasn't been signed in + // yet. + callback(nil, error); + return; + } + user.anonymous = anonymous; + [user updateWithGetAccountInfoResponse:response]; + callback(user, nil); + }]; + }]; +} + +- (instancetype)initWithTokenService:(FIRSecureTokenService *)tokenService { + self = [super init]; + if (self) { + _providerData = @{}; + _taskQueue = [[FIRAuthSerialTaskQueue alloc] init]; + _tokenService = tokenService; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *userID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserIDCodingKey]; + BOOL hasAnonymousKey = [aDecoder containsValueForKey:kAnonymousCodingKey]; + BOOL anonymous = [aDecoder decodeBoolForKey:kAnonymousCodingKey]; + BOOL hasEmailPasswordCredential = + [aDecoder decodeBoolForKey:kHasEmailPasswordCredentialCodingKey]; + NSString *displayName = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kDisplayNameCodingKey]; + NSURL *photoURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPhotoURLCodingKey]; + NSString *email = [aDecoder decodeObjectOfClass:[NSString class] forKey:kEmailCodingKey]; + NSString *phoneNumber = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kPhoneNumberCodingKey]; + BOOL emailVerified = [aDecoder decodeBoolForKey:kEmailVerifiedCodingKey]; + NSSet *providerDataClasses = + [NSSet setWithArray:@ [[NSDictionary class], [NSString class], [FIRUserInfoImpl class]]]; + NSDictionary *providerData = + [aDecoder decodeObjectOfClasses:providerDataClasses forKey:kProviderDataKey]; + FIRSecureTokenService *tokenService = [aDecoder decodeObjectOfClass:[FIRSecureTokenService class] + forKey:kTokenServiceCodingKey]; + FIRUserMetadata *metadata = [aDecoder decodeObjectOfClass:[FIRUserMetadata class] + forKey:kMetadataCodingKey]; + NSString *APIKey = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAPIKeyCodingKey]; +#if TARGET_OS_IOS + FIRMultiFactor *multiFactor = [aDecoder decodeObjectOfClass:[FIRMultiFactor class] + forKey:kMultiFactorCodingKey]; +#endif + if (!userID || !tokenService) { + return nil; + } + self = [self initWithTokenService:tokenService]; + if (self) { + _userID = userID; + // Previous version of this code didn't save 'anonymous' bit directly but deduced it from + // 'hasEmailPasswordCredential' and 'providerData' instead, so here backward compatibility is + // provided to read old format data. + _anonymous = hasAnonymousKey ? anonymous : (!hasEmailPasswordCredential && !providerData.count); + _hasEmailPasswordCredential = hasEmailPasswordCredential; + _email = email; + _emailVerified = emailVerified; + _displayName = displayName; + _photoURL = photoURL; + _providerData = providerData; + _phoneNumber = phoneNumber; + _metadata = metadata ?: [[FIRUserMetadata alloc] initWithCreationDate:nil lastSignInDate:nil]; + _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:APIKey]; +#if TARGET_OS_IOS + _multiFactor = multiFactor ?: [[FIRMultiFactor alloc] init]; +#endif + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_userID forKey:kUserIDCodingKey]; + [aCoder encodeBool:self.anonymous forKey:kAnonymousCodingKey]; + [aCoder encodeBool:_hasEmailPasswordCredential forKey:kHasEmailPasswordCredentialCodingKey]; + [aCoder encodeObject:_providerData forKey:kProviderDataKey]; + [aCoder encodeObject:_email forKey:kEmailCodingKey]; + [aCoder encodeObject:_phoneNumber forKey:kPhoneNumberCodingKey]; + [aCoder encodeBool:_emailVerified forKey:kEmailVerifiedCodingKey]; + [aCoder encodeObject:_photoURL forKey:kPhotoURLCodingKey]; + [aCoder encodeObject:_displayName forKey:kDisplayNameCodingKey]; + [aCoder encodeObject:_metadata forKey:kMetadataCodingKey]; + [aCoder encodeObject:_auth.requestConfiguration.APIKey forKey:kAPIKeyCodingKey]; + [aCoder encodeObject:_tokenService forKey:kTokenServiceCodingKey]; +#if TARGET_OS_IOS + [aCoder encodeObject:_multiFactor forKey:kMultiFactorCodingKey]; +#endif +} + +#pragma mark - + +- (void)setAuth:(nullable FIRAuth *)auth { + _auth = auth; + _tokenService.requestConfiguration = auth.requestConfiguration; +} + +- (NSString *)providerID { + return @"Firebase"; +} + +- (NSArray> *)providerData { + return _providerData.allValues; +} + +/** @fn getAccountInfoRefreshingCache: + @brief Gets the users's account data from the server, updating our local values. + @param callback Invoked when the request to getAccountInfo has completed, or when an error has + been detected. Invoked asynchronously on the auth global work queue in the future. + */ +- (void)getAccountInfoRefreshingCache:(void (^)(FIRGetAccountInfoResponseUser *_Nullable user, + NSError *_Nullable error))callback { + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + callback(nil, error); + return; + } + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken + requestConfiguration:self->_auth.requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + callback(nil, error); + return; + } + [self updateWithGetAccountInfoResponse:response]; + if (![self updateKeychain:&error]) { + callback(nil, error); + return; + } + callback(response.users.firstObject, nil); + }]; + }]; +} + +- (void)updateWithGetAccountInfoResponse:(FIRGetAccountInfoResponse *)response { + FIRGetAccountInfoResponseUser *user = response.users.firstObject; + _userID = user.localID; + _email = user.email; + _emailVerified = user.emailVerified; + _displayName = user.displayName; + _photoURL = user.photoURL; + _phoneNumber = user.phoneNumber; + _hasEmailPasswordCredential = user.passwordHash.length > 0; + _metadata = [[FIRUserMetadata alloc] initWithCreationDate:user.creationDate + lastSignInDate:user.lastLoginDate]; + NSMutableDictionary *providerData = + [NSMutableDictionary dictionary]; + for (FIRGetAccountInfoResponseProviderUserInfo *providerUserInfo in user.providerUserInfo) { + FIRUserInfoImpl *userInfo = + [FIRUserInfoImpl userInfoWithGetAccountInfoResponseProviderUserInfo:providerUserInfo]; + if (userInfo) { + providerData[providerUserInfo.providerID] = userInfo; + } + } + _providerData = [providerData copy]; +#if TARGET_OS_IOS + _multiFactor = [[FIRMultiFactor alloc] initWithMFAEnrollments:user.MFAEnrollments]; + _multiFactor.user = self; +#endif +} + +/** @fn executeUserUpdateWithChanges:callback: + @brief Performs a setAccountInfo request by mutating the results of a getAccountInfo response, + atomically in regards to other calls to this method. + @param changeBlock A block responsible for mutating a template @c FIRSetAccountInfoRequest + @param callback A block to invoke when the change is complete. Invoked asynchronously on the + auth global work queue in the future. + */ +- (void)executeUserUpdateWithChanges:(void (^)(FIRGetAccountInfoResponseUser *, + FIRSetAccountInfoRequest *))changeBlock + callback:(nonnull FIRUserProfileChangeCallback)callback { + [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) { + [self getAccountInfoRefreshingCache:^(FIRGetAccountInfoResponseUser *_Nullable user, + NSError *_Nullable error) { + if (error) { + complete(); + callback(error); + return; + } + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + complete(); + callback(error); + return; + } + FIRAuthRequestConfiguration *configuration = self->_auth.requestConfiguration; + // Mutate setAccountInfoRequest in block: + FIRSetAccountInfoRequest *setAccountInfoRequest = + [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:configuration]; + setAccountInfoRequest.accessToken = accessToken; + changeBlock(user, setAccountInfoRequest); + // Execute request: + [FIRAuthBackend + setAccountInfo:setAccountInfoRequest + callback:^(FIRSetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + complete(); + callback(error); + return; + } + if (response.IDToken && response.refreshToken) { + FIRSecureTokenService *tokenService = [[FIRSecureTokenService alloc] + initWithRequestConfiguration:configuration + accessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken]; + [self setTokenService:tokenService + callback:^(NSError *_Nullable error) { + complete(); + callback(error); + }]; + return; + } + complete(); + callback(nil); + }]; + }]; + }]; + }]; +} + +/** @fn updateKeychain: + @brief Updates the keychain for user token or info changes. + @param error The error if NO is returned. + @return Whether the operation is successful. + */ +- (BOOL)updateKeychain:(NSError *_Nullable *_Nullable)error { + return [_auth updateKeychainWithUser:self error:error]; +} + +/** @fn setTokenService:callback: + @brief Sets a new token service for the @c FIRUser instance. + @param tokenService The new token service object. + @param callback The block to be called in the global auth working queue once finished. + @remarks The method makes sure the token service has access and refresh token and the new tokens + are saved in the keychain before calling back. + */ +- (void)setTokenService:(FIRSecureTokenService *)tokenService + callback:(nonnull CallbackWithError)callback { + [tokenService fetchAccessTokenForcingRefresh:NO + callback:^(NSString *_Nullable token, + NSError *_Nullable error, BOOL tokenUpdated) { + if (error) { + callback(error); + return; + } + self->_tokenService = tokenService; + if (![self updateKeychain:&error]) { + callback(error); + return; + } + callback(nil); + }]; +} + +#pragma mark - + +/** @fn updateEmail:password:callback: + @brief Updates email address and/or password for the current user. + @remarks May fail if there is already an email/password-based account for the same email + address. + @param email The email address for the user, if to be updated. + @param password The new password for the user, if to be updated. + @param callback The block called when the user profile change has finished. Invoked + asynchronously on the auth global work queue in the future. + @remarks May fail with a @c FIRAuthErrorCodeRequiresRecentLogin error code. + Call @c reauthentateWithCredential:completion: beforehand to avoid this error case. + */ +- (void)updateEmail:(nullable NSString *)email + password:(nullable NSString *)password + callback:(nonnull FIRUserProfileChangeCallback)callback { + if (password && ![password length]) { + callback([FIRAuthErrorUtils weakPasswordErrorWithServerResponseReason:kMissingPasswordReason]); + return; + } + BOOL hadEmailPasswordCredential = _hasEmailPasswordCredential; + [self + executeUserUpdateWithChanges:^(FIRGetAccountInfoResponseUser *user, + FIRSetAccountInfoRequest *request) { + if (email) { + request.email = email; + } + if (password) { + request.password = password; + } + } + callback:^(NSError *error) { + if (error) { + callback(error); + return; + } + if (email) { + self->_email = [email copy]; + } + if (self->_email) { + if (!hadEmailPasswordCredential) { + // The list of providers need to be updated for the newly added email-password provider. + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + callback(error); + return; + } + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken + requestConfiguration:requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + callback(error); + return; + } + for (FIRGetAccountInfoResponseUser *userAccountInfo in response.users) { + // Set the account to non-anonymous if there are any providers, even if + // they're not email/password ones. + if (userAccountInfo.providerUserInfo.count > 0) { + self.anonymous = NO; + } + for (FIRGetAccountInfoResponseProviderUserInfo + *providerUserInfo in userAccountInfo.providerUserInfo) { + if ([providerUserInfo.providerID + isEqualToString:FIREmailAuthProviderID]) { + self->_hasEmailPasswordCredential = YES; + break; + } + } + } + [self updateWithGetAccountInfoResponse:response]; + if (![self updateKeychain:&error]) { + callback(error); + return; + } + callback(nil); + }]; + }]; + return; + } + } + if (![self updateKeychain:&error]) { + callback(error); + return; + } + callback(nil); + }]; +} + +- (void)updateEmail:(NSString *)email completion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self updateEmail:email + password:nil + callback:^(NSError *_Nullable error) { + callInMainThreadWithError(completion, error); + }]; + }); +} + +- (void)updatePassword:(NSString *)password + completion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self updateEmail:nil + password:password + callback:^(NSError *_Nullable error) { + callInMainThreadWithError(completion, error); + }]; + }); +} + +#if TARGET_OS_IOS +/** @fn internalUpdateOrLinkPhoneNumberCredential:completion: + @brief Updates the phone number for the user. On success, the cached user profile data is + updated. + + @param phoneAuthCredential The new phone number credential corresponding to the phone number + to be added to the Firebase account, if a phone number is already linked to the account this + new phone number will replace it. + @param isLinkOperation Boolean value indicating whether or not this is a link operation. + @param completion Optionally; the block invoked when the user profile change has finished. + Invoked asynchronously on the global work queue in the future. + */ +- (void)internalUpdateOrLinkPhoneNumberCredential:(FIRPhoneAuthCredential *)phoneAuthCredential + isLinkOperation:(BOOL)isLinkOperation + completion:(FIRUserProfileChangeCallback)completion { + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + completion(error); + return; + } + FIRAuthOperationType operation = + isLinkOperation ? FIRAuthOperationTypeLink : FIRAuthOperationTypeUpdate; + FIRVerifyPhoneNumberRequest *request = [[FIRVerifyPhoneNumberRequest alloc] + initWithVerificationID:phoneAuthCredential.verificationID + verificationCode:phoneAuthCredential.verificationCode + operation:operation + requestConfiguration:self->_auth.requestConfiguration]; + request.accessToken = accessToken; + [FIRAuthBackend verifyPhoneNumber:request + callback:^(FIRVerifyPhoneNumberResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + completion(error); + return; + } + // Get account info to update cached user info. + [self getAccountInfoRefreshingCache:^( + FIRGetAccountInfoResponseUser *_Nullable user, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + completion(error); + return; + } + self.anonymous = NO; + if (![self updateKeychain:&error]) { + completion(error); + return; + } + completion(nil); + }]; + }]; + }]; +} + +- (void)updatePhoneNumberCredential:(FIRPhoneAuthCredential *)phoneAuthCredential + completion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self internalUpdateOrLinkPhoneNumberCredential:phoneAuthCredential + isLinkOperation:NO + completion:^(NSError *_Nullable error) { + callInMainThreadWithError(completion, error); + }]; + }); +} +#endif + +- (FIRUserProfileChangeRequest *)profileChangeRequest { + __block FIRUserProfileChangeRequest *result; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = [[FIRUserProfileChangeRequest alloc] initWithUser:self]; + }); + return result; +} + +- (void)setDisplayName:(NSString *)displayName { + _displayName = [displayName copy]; +} + +- (void)setPhotoURL:(NSURL *)photoURL { + _photoURL = [photoURL copy]; +} + +- (NSString *)rawAccessToken { + return _tokenService.rawAccessToken; +} + +- (NSDate *)accessTokenExpirationDate { + return _tokenService.accessTokenExpirationDate; +} + +#pragma mark - + +- (void)reloadWithCompletion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self getAccountInfoRefreshingCache:^(FIRGetAccountInfoResponseUser *_Nullable user, + NSError *_Nullable error) { + callInMainThreadWithError(completion, error); + }]; + }); +} + +#pragma mark - + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (void)reauthenticateWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + [self reauthenticateAndRetrieveDataWithCredential:credential completion:completion]; +} +#pragma clang diagnostic pop + +- (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self->_auth + internalSignInAndRetrieveDataWithCredential:credential + isReauthentication:YES + callback:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + if (error) { + // If "user not found" error returned by backend, + // translate to user mismatch error which is more + // accurate. + if (error.code == FIRAuthErrorCodeUserNotFound) { + error = [FIRAuthErrorUtils userMismatchError]; + } + callInMainThreadWithAuthDataResultAndError( + completion, authResult, error); + return; + } + if (![authResult.user.uid + isEqual:[self->_auth getUserID]]) { + callInMainThreadWithAuthDataResultAndError( + completion, authResult, + [FIRAuthErrorUtils userMismatchError]); + return; + } + // Successful reauthenticate + [self + setTokenService:authResult.user->_tokenService + callback:^(NSError *_Nullable error) { + callInMainThreadWithAuthDataResultAndError( + completion, authResult, error); + }]; + }]; + }); +} + +- (void)reauthenticateWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion { +#if TARGET_OS_IOS + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [provider getCredentialWithUIDelegate:UIDelegate + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + [self reauthenticateWithCredential:credential + completion:completion]; + }]; + }); +#endif // TARGET_OS_IOS +} + +- (nullable NSString *)refreshToken { + __block NSString *result; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + result = self->_tokenService.refreshToken; + }); + return result; +} + +- (void)getIDTokenWithCompletion:(nullable FIRAuthTokenCallback)completion { + // |getIDTokenForcingRefresh:completion:| is also a public API so there is no need to dispatch to + // global work queue here. + [self getIDTokenForcingRefresh:NO completion:completion]; +} + +- (void)getIDTokenForcingRefresh:(BOOL)forceRefresh + completion:(nullable FIRAuthTokenCallback)completion { + [self getIDTokenResultForcingRefresh:forceRefresh + completion:^(FIRAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(tokenResult.token, error); + }); + } + }]; +} + +- (void)getIDTokenResultWithCompletion:(nullable FIRAuthTokenResultCallback)completion { + [self getIDTokenResultForcingRefresh:NO + completion:^(FIRAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) { + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(tokenResult, error); + }); + } + }]; +} + +- (void)getIDTokenResultForcingRefresh:(BOOL)forceRefresh + completion:(nullable FIRAuthTokenResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self internalGetTokenForcingRefresh:forceRefresh + callback:^(NSString *_Nullable token, NSError *_Nullable error) { + FIRAuthTokenResult *tokenResult; + if (token) { + tokenResult = [FIRAuthTokenResult tokenResultWithToken:token]; + } + if (completion) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(tokenResult, error); + }); + } + }]; + }); +} + +/** @fn parseIDToken:error: + @brief Parses the provided IDToken and returns an instance of FIRAuthTokenResult containing + claims obtained from the IDToken. + + @param token The raw text of the Firebase IDToken encoded in base64. + @param error An out parameter which would contain any error that occurs during parsing. + @return An instance of FIRAuthTokenResult containing claims obtained from the IDToken. + + @remarks IDToken returned from the backend in some cases is of a length that is not a multiple + of 4. In these cases this function pads the token with as many "=" characters as needed and + then attempts to parse the token. If the token cannot be parsed an error is returned via the + "error" out parameter. + */ +- (nullable FIRAuthTokenResult *)parseIDToken:(NSString *)token error:(NSError **)error { + // Though this is an internal method, errors returned here are surfaced in user-visible + // callbacks. + if (error) { + *error = nil; + } + NSArray *tokenStringArray = [token componentsSeparatedByString:@"."]; + + // The JWT should have three parts, though we only use the second in this method. + if (tokenStringArray.count != 3) { + if (error) { + *error = [FIRAuthErrorUtils malformedJWTErrorWithToken:token underlyingError:nil]; + } + return nil; + } + + // The token payload is always the second index of the array. + NSString *IDToken = tokenStringArray[1]; + + // Convert the base64URL encoded string to a base64 encoded string. + // Replace "_" with "/" + NSMutableString *tokenPayload = [[IDToken stringByReplacingOccurrencesOfString:@"_" + withString:@"/"] mutableCopy]; + + // Replace "-" with "+" + [tokenPayload replaceOccurrencesOfString:@"-" + withString:@"+" + options:kNilOptions + range:NSMakeRange(0, tokenPayload.length)]; + + // Pad the token payload with "=" signs if the payload's length is not a multiple of 4. + while ((tokenPayload.length % 4) != 0) { + [tokenPayload appendFormat:@"="]; + } + NSData *decodedTokenPayloadData = + [[NSData alloc] initWithBase64EncodedString:tokenPayload + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + if (!decodedTokenPayloadData) { + if (error) { + *error = [FIRAuthErrorUtils malformedJWTErrorWithToken:token underlyingError:nil]; + } + return nil; + } + NSError *jsonError = nil; + NSJSONReadingOptions options = NSJSONReadingMutableContainers | NSJSONReadingAllowFragments; + NSDictionary *tokenPayloadDictionary = + [NSJSONSerialization JSONObjectWithData:decodedTokenPayloadData + options:options + error:&jsonError]; + if (jsonError != nil) { + if (error) { + *error = [FIRAuthErrorUtils malformedJWTErrorWithToken:token underlyingError:jsonError]; + } + return nil; + } + + if (!tokenPayloadDictionary) { + if (error) { + *error = [FIRAuthErrorUtils malformedJWTErrorWithToken:token underlyingError:nil]; + } + return nil; + } + + FIRAuthTokenResult *result = [FIRAuthTokenResult tokenResultWithToken:token]; + return result; +} + +/** @fn internalGetTokenForcingRefresh:callback: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + @param callback The block to invoke when the token is available. Invoked asynchronously on the + global work thread in the future. + */ +- (void)internalGetTokenWithCallback:(nonnull FIRAuthTokenCallback)callback { + [self internalGetTokenForcingRefresh:NO callback:callback]; +} + +- (void)internalGetTokenForcingRefresh:(BOOL)forceRefresh + callback:(nonnull FIRAuthTokenCallback)callback { + [_tokenService fetchAccessTokenForcingRefresh:forceRefresh + callback:^(NSString *_Nullable token, + NSError *_Nullable error, BOOL tokenUpdated) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + callback(nil, error); + return; + } + if (tokenUpdated) { + if (![self updateKeychain:&error]) { + callback(nil, error); + return; + } + } + callback(token, nil); + }]; +} + +- (void)sendEmailVerificationBeforeUpdatingEmail:(nonnull NSString *)email + completion:(nullable FIRAuthVoidErrorCallback)completion { + [self internalVerifyBeforeUpdateEmailWithNewEmail:email + actionCodeSettings:nil + completion:completion]; +} + +- (void)sendEmailVerificationBeforeUpdatingEmail:(nonnull NSString *)email + actionCodeSettings:(nonnull FIRActionCodeSettings *)actionCodeSettings + completion:(nullable FIRAuthVoidErrorCallback)completion { + [self internalVerifyBeforeUpdateEmailWithNewEmail:email + actionCodeSettings:actionCodeSettings + completion:completion]; +} + +- (void)internalVerifyBeforeUpdateEmailWithNewEmail:(NSString *)newEmail + actionCodeSettings: + (nullable FIRActionCodeSettings *)actionCodeSettings + completion:(FIRVerifyBeforeUpdateEmailCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self + internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + callInMainThreadWithError(completion, error); + return; + } + FIRAuthRequestConfiguration *configuration = self->_auth.requestConfiguration; + FIRActionCodeSettings *settings = actionCodeSettings; + FIRGetOOBConfirmationCodeRequest *request = [FIRGetOOBConfirmationCodeRequest + verifyBeforeUpdateEmailWithAccessToken:accessToken + newEmail:newEmail + actionCodeSettings:settings + requestConfiguration:configuration]; + [FIRAuthBackend + getOOBConfirmationCode:request + callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response, + NSError *_Nullable error) { + callInMainThreadWithError(completion, error); + }]; + }]; + }); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +- (void)linkWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + [self linkAndRetrieveDataWithCredential:credential completion:completion]; +} +#pragma clang diagnostic pop + +- (void)linkAndRetrieveDataWithCredential:(FIRAuthCredential *)credential + completion:(nullable FIRAuthDataResultCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + if (self->_providerData[credential.provider]) { + callInMainThreadWithAuthDataResultAndError(completion, nil, + [FIRAuthErrorUtils providerAlreadyLinkedError]); + return; + } + FIRAuthDataResult *result = [[FIRAuthDataResult alloc] initWithUser:self + additionalUserInfo:nil]; + if ([credential isKindOfClass:[FIREmailPasswordAuthCredential class]]) { + if (self->_hasEmailPasswordCredential) { + callInMainThreadWithAuthDataResultAndError(completion, nil, + [FIRAuthErrorUtils providerAlreadyLinkedError]); + return; + } + FIREmailPasswordAuthCredential *emailPasswordCredential = + (FIREmailPasswordAuthCredential *)credential; + if (emailPasswordCredential.password) { + [self updateEmail:emailPasswordCredential.email + password:emailPasswordCredential.password + callback:^(NSError *error) { + if (error) { + callInMainThreadWithAuthDataResultAndError(completion, nil, error); + } else { + callInMainThreadWithAuthDataResultAndError(completion, result, nil); + } + }]; + } else { + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + NSDictionary *queryItems = + [FIRAuthWebUtils parseURL:emailPasswordCredential.link]; + if (![queryItems count]) { + NSURLComponents *urlComponents = + [NSURLComponents componentsWithString:emailPasswordCredential.link]; + queryItems = [FIRAuthWebUtils parseURL:urlComponents.query]; + } + NSString *actionCode = queryItems[@"oobCode"]; + FIRAuthRequestConfiguration *requestConfiguration = self.auth.requestConfiguration; + FIREmailLinkSignInRequest *request = + [[FIREmailLinkSignInRequest alloc] initWithEmail:emailPasswordCredential.email + oobCode:actionCode + requestConfiguration:requestConfiguration]; + request.IDToken = accessToken; + [FIRAuthBackend + emailLinkSignin:request + callback:^(FIREmailLinkSignInResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + callInMainThreadWithAuthDataResultAndError(completion, nil, error); + } else { + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + callInMainThreadWithAuthDataResultAndError(completion, nil, error); + return; + } + + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] + initWithAccessToken:accessToken + requestConfiguration:requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + callInMainThreadWithAuthDataResultAndError(completion, nil, + error); + return; + } + self.anonymous = NO; + [self updateWithGetAccountInfoResponse:response]; + if (![self updateKeychain:&error]) { + callInMainThreadWithAuthDataResultAndError(completion, nil, + error); + return; + } + callInMainThreadWithAuthDataResultAndError(completion, + result, nil); + }]; + }]; + } + }]; + }]; + } + return; + } + + if ([credential isKindOfClass:[FIRGameCenterAuthCredential class]]) { + FIRGameCenterAuthCredential *gameCenterCredential = (FIRGameCenterAuthCredential *)credential; + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + FIRAuthRequestConfiguration *requestConfiguration = self.auth.requestConfiguration; + FIRSignInWithGameCenterRequest *gameCenterRequest = [[FIRSignInWithGameCenterRequest alloc] + initWithPlayerID:gameCenterCredential.playerID + publicKeyURL:gameCenterCredential.publicKeyURL + signature:gameCenterCredential.signature + salt:gameCenterCredential.salt + timestamp:gameCenterCredential.timestamp + displayName:gameCenterCredential.displayName + requestConfiguration:requestConfiguration]; + gameCenterRequest.accessToken = accessToken; + + [FIRAuthBackend + signInWithGameCenter:gameCenterRequest + callback:^(FIRSignInWithGameCenterResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + callInMainThreadWithAuthDataResultAndError(completion, nil, error); + } else { + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + callInMainThreadWithAuthDataResultAndError(completion, nil, error); + return; + } + + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] + initWithAccessToken:accessToken + requestConfiguration:requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + callInMainThreadWithAuthDataResultAndError(completion, + nil, error); + return; + } + self.anonymous = NO; + [self updateWithGetAccountInfoResponse:response]; + if (![self updateKeychain:&error]) { + callInMainThreadWithAuthDataResultAndError(completion, + nil, error); + return; + } + callInMainThreadWithAuthDataResultAndError(completion, + result, nil); + }]; + }]; + } + }]; + }]; + return; + } + +#if TARGET_OS_IOS + if ([credential isKindOfClass:[FIRPhoneAuthCredential class]]) { + FIRPhoneAuthCredential *phoneAuthCredential = (FIRPhoneAuthCredential *)credential; + [self internalUpdateOrLinkPhoneNumberCredential:phoneAuthCredential + isLinkOperation:YES + completion:^(NSError *_Nullable error) { + if (error) { + callInMainThreadWithAuthDataResultAndError( + completion, nil, error); + } else { + callInMainThreadWithAuthDataResultAndError( + completion, result, nil); + } + }]; + return; + } +#endif + + [self->_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) { + CallbackWithAuthDataResultAndError completeWithError = + ^(FIRAuthDataResult *result, NSError *error) { + complete(); + callInMainThreadWithAuthDataResultAndError(completion, result, error); + }; + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + completeWithError(nil, error); + return; + } + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; + FIRVerifyAssertionRequest *request = + [[FIRVerifyAssertionRequest alloc] initWithProviderID:credential.provider + requestConfiguration:requestConfiguration]; + [credential prepareVerifyAssertionRequest:request]; + request.accessToken = accessToken; + [FIRAuthBackend + verifyAssertion:request + callback:^(FIRVerifyAssertionResponse *response, NSError *error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + completeWithError(nil, error); + return; + } + FIRAdditionalUserInfo *additionalUserInfo = + [FIRAdditionalUserInfo userInfoWithVerifyAssertionResponse:response]; + FIROAuthCredential *updatedOAuthCredential = + [[FIROAuthCredential alloc] initWithVerifyAssertionResponse:response]; + FIRAuthDataResult *result = + [[FIRAuthDataResult alloc] initWithUser:self + additionalUserInfo:additionalUserInfo + credential:updatedOAuthCredential]; + // Update the new token and refresh user info again. + self->_tokenService = [[FIRSecureTokenService alloc] + initWithRequestConfiguration:requestConfiguration + accessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken]; + [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, + NSError *_Nullable error) { + if (error) { + completeWithError(nil, error); + return; + } + FIRGetAccountInfoRequest *getAccountInfoRequest = + [[FIRGetAccountInfoRequest alloc] + initWithAccessToken:accessToken + requestConfiguration:requestConfiguration]; + [FIRAuthBackend + getAccountInfo:getAccountInfoRequest + callback:^(FIRGetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + completeWithError(nil, error); + return; + } + self.anonymous = NO; + [self updateWithGetAccountInfoResponse:response]; + if (![self updateKeychain:&error]) { + completeWithError(nil, error); + return; + } + completeWithError(result, nil); + }]; + }]; + }]; + }]; + }]; + }); +} + +- (void)linkWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion { +#if TARGET_OS_IOS + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [provider getCredentialWithUIDelegate:UIDelegate + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + [self linkWithCredential:credential completion:completion]; + }]; + }); +#endif // TARGET_OS_IOS +} + +- (void)unlinkFromProvider:(NSString *)provider + completion:(nullable FIRAuthResultCallback)completion { + [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) { + CallbackWithError completeAndCallbackWithError = ^(NSError *error) { + complete(); + callInMainThreadWithUserAndError(completion, self, error); + }; + [self + internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + completeAndCallbackWithError(error); + return; + } + FIRAuthRequestConfiguration *requestConfiguration = self->_auth.requestConfiguration; + FIRSetAccountInfoRequest *setAccountInfoRequest = + [[FIRSetAccountInfoRequest alloc] initWithRequestConfiguration:requestConfiguration]; + setAccountInfoRequest.accessToken = accessToken; + + if (!self->_providerData[provider]) { + completeAndCallbackWithError([FIRAuthErrorUtils noSuchProviderError]); + return; + } + setAccountInfoRequest.deleteProviders = @[ provider ]; + + [FIRAuthBackend + setAccountInfo:setAccountInfoRequest + callback:^(FIRSetAccountInfoResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + [self signOutIfTokenIsInvalidWithError:error]; + completeAndCallbackWithError(error); + return; + } + + // We can't just use the provider info objects in FIRSetAccountInfoResponse + // because they don't have localID and email fields. Remove the specific + // provider manually. + NSMutableDictionary *mutableProviderData = [self->_providerData mutableCopy]; + [mutableProviderData removeObjectForKey:provider]; + self->_providerData = [mutableProviderData copy]; + + if ([provider isEqualToString:FIREmailAuthProviderID]) { + self->_hasEmailPasswordCredential = NO; + } +#if TARGET_OS_IOS + // After successfully unlinking a phone auth provider, remove the phone number + // from the cached user info. + if ([provider isEqualToString:FIRPhoneAuthProviderID]) { + self->_phoneNumber = nil; + } +#endif + + if (response.IDToken && response.refreshToken) { + FIRSecureTokenService *tokenService = [[FIRSecureTokenService alloc] + initWithRequestConfiguration:requestConfiguration + accessToken:response.IDToken + accessTokenExpirationDate:response.approximateExpirationDate + refreshToken:response.refreshToken]; + [self setTokenService:tokenService + callback:^(NSError *_Nullable error) { + completeAndCallbackWithError(error); + }]; + return; + } + if (![self updateKeychain:&error]) { + completeAndCallbackWithError(error); + return; + } + completeAndCallbackWithError(nil); + }]; + }]; + }]; +} + +- (void)sendEmailVerificationWithCompletion:(nullable FIRSendEmailVerificationCallback)completion { + [self sendEmailVerificationWithNullableActionCodeSettings:nil completion:completion]; +} + +- (void)sendEmailVerificationWithActionCodeSettings:(FIRActionCodeSettings *)actionCodeSettings + completion: + (nullable FIRSendEmailVerificationCallback)completion { + [self sendEmailVerificationWithNullableActionCodeSettings:actionCodeSettings + completion:completion]; +} + +/** @fn sendEmailVerificationWithNullableActionCodeSettings:completion: + @brief Initiates email verification for the user. + + @param actionCodeSettings Optionally, a @c FIRActionCodeSettings object containing settings + related to the handling action codes. + */ +- (void)sendEmailVerificationWithNullableActionCodeSettings: + (nullable FIRActionCodeSettings *)actionCodeSettings + completion: + (nullable FIRSendEmailVerificationCallback) + completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self + internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + callInMainThreadWithError(completion, error); + return; + } + FIRAuthRequestConfiguration *configuration = self->_auth.requestConfiguration; + FIRGetOOBConfirmationCodeRequest *request = + [FIRGetOOBConfirmationCodeRequest verifyEmailRequestWithAccessToken:accessToken + actionCodeSettings:actionCodeSettings + requestConfiguration:configuration]; + [FIRAuthBackend + getOOBConfirmationCode:request + callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response, + NSError *_Nullable error) { + [self signOutIfTokenIsInvalidWithError:error]; + callInMainThreadWithError(completion, error); + }]; + }]; + }); +} + +- (void)deleteWithCompletion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_async(FIRAuthGlobalWorkQueue(), ^{ + [self + internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { + if (error) { + callInMainThreadWithError(completion, error); + return; + } + FIRDeleteAccountRequest *deleteUserRequest = + [[FIRDeleteAccountRequest alloc] initWitLocalID:self->_userID + accessToken:accessToken + requestConfiguration:self->_auth.requestConfiguration]; + [FIRAuthBackend deleteAccount:deleteUserRequest + callback:^(NSError *_Nullable error) { + if (error) { + callInMainThreadWithError(completion, error); + return; + } + if (![self->_auth signOutByForceWithUserID:self->_userID + error:&error]) { + callInMainThreadWithError(completion, error); + return; + } + callInMainThreadWithError(completion, error); + }]; + }]; + }); +} + +/** @fn signOutIfTokenIsInvalidWithError: + @brief Signs out this user if the user or the token is invalid. + @param error The error from the server. + */ +- (void)signOutIfTokenIsInvalidWithError:(nullable NSError *)error { + NSInteger errorCode = error.code; + if (errorCode == FIRAuthErrorCodeUserNotFound || errorCode == FIRAuthErrorCodeUserDisabled || + errorCode == FIRAuthErrorCodeInvalidUserToken || + errorCode == FIRAuthErrorCodeUserTokenExpired) { + FIRLogNotice(kFIRLoggerAuth, @"I-AUT000016", + @"Invalid user token detected, user is automatically signed out."); + [_auth signOutByForceWithUserID:_userID error:NULL]; + } +} + +@end + +@implementation FIRUserProfileChangeRequest { + /** @var _user + @brief The user associated with the change request. + */ + FIRUser *_user; + + /** @var _displayName + @brief The display name value to set if @c _displayNameSet is YES. + */ + NSString *_displayName; + + /** @var _displayNameSet + @brief Indicates the display name should be part of the change request. + */ + BOOL _displayNameSet; + + /** @var _photoURL + @brief The photo URL value to set if @c _displayNameSet is YES. + */ + NSURL *_photoURL; + + /** @var _photoURLSet + @brief Indicates the photo URL should be part of the change request. + */ + BOOL _photoURLSet; + + /** @var _consumed + @brief Indicates the @c commitChangesWithCallback: method has already been invoked. + */ + BOOL _consumed; +} + +- (nullable instancetype)initWithUser:(FIRUser *)user { + self = [super init]; + if (self) { + _user = user; + } + return self; +} + +- (nullable NSString *)displayName { + return _displayName; +} + +- (void)setDisplayName:(nullable NSString *)displayName { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + if (self->_consumed) { + [NSException + raise:NSInternalInconsistencyException + format:@"%@", @"Invalid call to setDisplayName: after commitChangesWithCallback:."]; + return; + } + self->_displayNameSet = YES; + self->_displayName = [displayName copy]; + }); +} + +- (nullable NSURL *)photoURL { + return _photoURL; +} + +- (void)setPhotoURL:(nullable NSURL *)photoURL { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + if (self->_consumed) { + [NSException raise:NSInternalInconsistencyException + format:@"%@", @"Invalid call to setPhotoURL: after commitChangesWithCallback:."]; + return; + } + self->_photoURLSet = YES; + self->_photoURL = [photoURL copy]; + }); +} + +/** @fn hasUpdates + @brief Indicates at least one field has a value which needs to be committed. + */ +- (BOOL)hasUpdates { + return _displayNameSet || _photoURLSet; +} + +- (void)commitChangesWithCompletion:(nullable FIRUserProfileChangeCallback)completion { + dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ + if (self->_consumed) { + [NSException raise:NSInternalInconsistencyException + format:@"%@", @"commitChangesWithCallback: should only be called once."]; + return; + } + self->_consumed = YES; + // Return fast if there is nothing to update: + if (![self hasUpdates]) { + callInMainThreadWithError(completion, nil); + return; + } + NSString *displayName = [self->_displayName copy]; + BOOL displayNameWasSet = self->_displayNameSet; + NSURL *photoURL = [self->_photoURL copy]; + BOOL photoURLWasSet = self->_photoURLSet; + [self->_user + executeUserUpdateWithChanges:^(FIRGetAccountInfoResponseUser *user, + FIRSetAccountInfoRequest *request) { + if (photoURLWasSet) { + request.photoURL = photoURL; + } + if (displayNameWasSet) { + request.displayName = displayName; + } + } + callback:^(NSError *_Nullable error) { + if (error) { + callInMainThreadWithError(completion, error); + return; + } + if (displayNameWasSet) { + [self->_user setDisplayName:displayName]; + } + if (photoURLWasSet) { + [self->_user setPhotoURL:photoURL]; + } + if (![self->_user updateKeychain:&error]) { + callInMainThreadWithError(completion, error); + return; + } + callInMainThreadWithError(completion, nil); + }]; + }); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.h new file mode 100644 index 00000000..45b9f038 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRGetAccountInfoResponseProviderUserInfo; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRUserInfoImpl : NSObject + +/** @fn userInfoWithGetAccountInfoResponseProviderUserInfo: + @brief A convenience factory method for constructing a @c FIRUserInfo instance from data + returned by the getAccountInfo endpoint. + @param providerUserInfo Data returned by the getAccountInfo endpoint. + @return A new instance of @c FIRUserInfo using data from the getAccountInfo endpoint. + */ ++ (nullable instancetype)userInfoWithGetAccountInfoResponseProviderUserInfo: + (FIRGetAccountInfoResponseProviderUserInfo *)providerUserInfo; + +/** @fn init + @brief This class should not be initialized manually. + @see FIRUser.providerData + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithProviderID:userID:displayName:photoURL:email: + @brief Designated initializer. + @param providerID The provider identifier. + @param userID The unique user ID for the user (the value of the @c uid field in the token.) + @param displayName The name of the user. + @param photoURL The URL of the user's profile photo. + @param email The user's email address. + @param phoneNumber The user's phone number. + */ +- (nullable instancetype)initWithProviderID:(NSString *)providerID + userID:(NSString *)userID + displayName:(nullable NSString *)displayName + photoURL:(nullable NSURL *)photoURL + email:(nullable NSString *)email + phoneNumber:(nullable NSString *)phoneNumber + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.m new file mode 100644 index 00000000..50926067 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserInfoImpl.m @@ -0,0 +1,131 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/User/FIRUserInfoImpl.h" + +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kProviderIDCodingKey + @brief The key used to encode the providerID property for NSSecureCoding. + */ +static NSString *const kProviderIDCodingKey = @"providerID"; + +/** @var kUserIDCodingKey + @brief The key used to encode the userID property for NSSecureCoding. + */ +static NSString *const kUserIDCodingKey = @"userID"; + +/** @var kDisplayNameCodingKey + @brief The key used to encode the displayName property for NSSecureCoding. + */ +static NSString *const kDisplayNameCodingKey = @"displayName"; + +/** @var kProfileURLCodingKey + @brief The key used to encode the profileURL property for NSSecureCoding. + */ +static NSString *const kProfileURLCodingKey = @"profileURL"; + +/** @var kPhotoURLCodingKey + @brief The key used to encode the photoURL property for NSSecureCoding. + */ +static NSString *const kPhotoURLCodingKey = @"photoURL"; + +/** @var kEmailCodingKey + @brief The key used to encode the email property for NSSecureCoding. + */ +static NSString *const kEmailCodingKey = @"email"; + +/** @var kPhoneNumberCodingKey + @brief The key used to encode the phoneNumber property for NSSecureCoding. + */ +static NSString *const kPhoneNumberCodingKey = @"phoneNumber"; + +@implementation FIRUserInfoImpl + +@synthesize providerID = _providerID; +@synthesize uid = _userID; +@synthesize displayName = _displayName; +@synthesize photoURL = _photoURL; +@synthesize email = _email; +@synthesize phoneNumber = _phoneNumber; + ++ (nullable instancetype)userInfoWithGetAccountInfoResponseProviderUserInfo: + (FIRGetAccountInfoResponseProviderUserInfo *)providerUserInfo { + return [[self alloc] initWithProviderID:providerUserInfo.providerID + userID:providerUserInfo.federatedID + displayName:providerUserInfo.displayName + photoURL:providerUserInfo.photoURL + email:providerUserInfo.email + phoneNumber:providerUserInfo.phoneNumber]; +} + +- (nullable instancetype)initWithProviderID:(NSString *)providerID + userID:(NSString *)userID + displayName:(nullable NSString *)displayName + photoURL:(nullable NSURL *)photoURL + email:(nullable NSString *)email + phoneNumber:(nullable NSString *)phoneNumber { + self = [super init]; + if (self) { + _providerID = [providerID copy]; + _userID = [userID copy]; + _displayName = [displayName copy]; + _photoURL = [photoURL copy]; + _email = [email copy]; + _phoneNumber = [phoneNumber copy]; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *providerID = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kProviderIDCodingKey]; + NSString *userID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserIDCodingKey]; + NSString *displayName = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kDisplayNameCodingKey]; + NSURL *photoURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPhotoURLCodingKey]; + NSString *email = [aDecoder decodeObjectOfClass:[NSString class] forKey:kEmailCodingKey]; + NSString *phoneNumber = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kPhoneNumberCodingKey]; + + return [self initWithProviderID:providerID + userID:userID + displayName:displayName + photoURL:photoURL + email:email + phoneNumber:phoneNumber]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_providerID forKey:kProviderIDCodingKey]; + [aCoder encodeObject:_userID forKey:kUserIDCodingKey]; + [aCoder encodeObject:_displayName forKey:kDisplayNameCodingKey]; + [aCoder encodeObject:_photoURL forKey:kPhotoURLCodingKey]; + [aCoder encodeObject:_email forKey:kEmailCodingKey]; + [aCoder encodeObject:_phoneNumber forKey:kPhoneNumberCodingKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata.m new file mode 100644 index 00000000..ba46ebd4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata.m @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRUserMetadata + +/** @var kCreationDateCodingKey + @brief The key used to encode the creationDate property for NSSecureCoding. + */ +static NSString *const kCreationDateCodingKey = @"creationDate"; + +/** @var kLastSignInDateCodingKey + @brief The key used to encode the lastSignInDate property for NSSecureCoding. + */ +static NSString *const kLastSignInDateCodingKey = @"lastSignInDate"; + +- (instancetype)initWithCreationDate:(nullable NSDate *)creationDate + lastSignInDate:(nullable NSDate *)lastSignInDate { + self = [super init]; + if (self) { + _creationDate = [creationDate copy]; + _lastSignInDate = [lastSignInDate copy]; + } + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSDate *creationDate = [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kCreationDateCodingKey]; + NSDate *lastSignInDate = [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kLastSignInDateCodingKey]; + return [self initWithCreationDate:creationDate lastSignInDate:lastSignInDate]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_creationDate forKey:kCreationDateCodingKey]; + [aCoder encodeObject:_lastSignInDate forKey:kLastSignInDateCodingKey]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h new file mode 100644 index 00000000..7348bf2d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @extension FIRUserMetadata + @brief An internal class used to expose internal methods of FIRUserMetadata. + */ +@interface FIRUserMetadata () + +/** @fn initWithCreationDate:lastSignInDate: + @brief Designated initializer. + @param creationDate The creation date of the corresponding user. + @param lastSignInDate The date of the last recorded sign-in of the corresponding user. + */ +- (instancetype)initWithCreationDate:(nullable NSDate *)creationDate + lastSignInDate:(nullable NSDate *)lastSignInDate NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser_Internal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser_Internal.h new file mode 100644 index 00000000..99a1197e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/User/FIRUser_Internal.h @@ -0,0 +1,107 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuth; +@class FIRAuthRequestConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRRetrieveUserCallback + @brief The type of block that is invoked when the construction of a user succeeds or fails. + @param user The user that was constructed, or nil if user construction failed. + @param error The error which occurred, or nil if the request was successful. + */ +typedef void (^FIRRetrieveUserCallback)(FIRUser *_Nullable user, NSError *_Nullable error); + +/** @typedef FIRVerifyBeforeUpdateEmailCallback + @brief The type of block called when a request to verify before update email has finished. + @param error Optionally; the error which occurred - or nil if the request was successful. + */ +typedef void (^FIRVerifyBeforeUpdateEmailCallback)(NSError *_Nullable error); + +@interface FIRUser () + +/** @property rawAccessToken + @brief The cached access token. + @remarks This method is specifically for providing the access token to internal clients during + deserialization and sign-in events, and should not be used to retrieve the access token by + anyone else. + */ +@property(nonatomic, copy, readonly) NSString *rawAccessToken; + +/** @property auth + @brief A weak reference to a FIRAuth instance associated with this instance. + */ +@property(nonatomic, weak) FIRAuth *auth; + +/** @property auth + @brief A strong reference to a requestConfiguration instance associated with this user instance. + */ +@property(nonatomic, strong) FIRAuthRequestConfiguration *requestConfiguration; + +/** @var accessTokenExpirationDate + @brief The expiration date of the cached access token. + */ +@property(nonatomic, copy, readonly) NSDate *accessTokenExpirationDate; + +/** @fn retrieveUserWithAuth:accessToken:accessTokenExpirationDate:refreshToken:callback: + @brief Constructs a user with Secure Token Service tokens, and obtains user details from the + getAccountInfo endpoint. + @param auth The associated FIRAuth instance. + @param accessToken The Secure Token Service access token. + @param accessTokenExpirationDate The approximate expiration date of the access token. + @param refreshToken The Secure Token Service refresh token. + @param anonymous Whether or not the user is anonymous. + @param callback A block which is invoked when the construction succeeds or fails. Invoked + asynchronously on the auth global work queue in the future. + */ ++ (void)retrieveUserWithAuth:(FIRAuth *)auth + accessToken:(nullable NSString *)accessToken + accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate + refreshToken:(nullable NSString *)refreshToken + anonymous:(BOOL)anonymous + callback:(FIRRetrieveUserCallback)callback; + +/** @fn internalGetTokenForcingRefresh:callback: + @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. + @param forceRefresh Forces a token refresh. Useful if the token becomes invalid for some reason + other than an expiration. + @param callback The block to invoke when the token is available. Invoked asynchronously on the + global work thread in the future. + */ +- (void)internalGetTokenForcingRefresh:(BOOL)forceRefresh + callback:(nonnull FIRAuthTokenCallback)callback; + +/** @fn internalVerifyBeforeUpdateEmailWithNewEmail:actionCodeSettings:callback: + @brief Sends a verification email to newEmail. Upon redemption of the link in the email, + this user's email will be changed to newEmail and that email will be marked verified. + @param newEmail the user's new email. + @param actionCodeSettings the optional FIRActionCodeSettings object to allow linking back + to your app in the email. + @param completion The block to invoke when the call succeeds or fails. Invoked asynchronously on + the global work thread in the future. + + */ +- (void)internalVerifyBeforeUpdateEmailWithNewEmail:(NSString *)newEmail + actionCodeSettings: + (nullable FIRActionCodeSettings *)actionCodeSettings + completion:(FIRVerifyBeforeUpdateEmailCallback)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h new file mode 100644 index 00000000..57131c15 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthDefaultUIDelegate + @brief Class responsible for providing a default FIRAuthUIDelegte. + @remarks This class should be used in the case that a UIDelegate was expected and necessary to + continue a given flow, but none was provided. + */ +@interface FIRAuthDefaultUIDelegate : NSObject + +/** @fn defaultUIDelegate + @brief Unavailable. Please use @c +defaultUIDelegate: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn defaultUIDelegate + @brief Returns a default FIRAuthUIDelegate object. + @return The default FIRAuthUIDelegate object. + */ ++ (id)defaultUIDelegate; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.m new file mode 100644 index 00000000..2ba27a5a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.m @@ -0,0 +1,126 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if !TARGET_OS_OSX + +#import +#import + +#import "FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthDefaultUIDelegate () + +/** @fn initWithViewController: + @brief Initializes the instance with a view controller. + @param viewController The view controller as the presenting view controller in @c + FIRAuthUIDelegate. + @return The initialized instance. + */ +- (instancetype)initWithViewController:(nullable UIViewController *)viewController + NS_DESIGNATED_INITIALIZER; + +@end + +@implementation FIRAuthDefaultUIDelegate { + /** @var _viewController + @brief The presenting view controller. + */ + UIViewController *_viewController; +} + +- (instancetype)initWithViewController:(nullable UIViewController *)viewController { + self = [super init]; + if (self) { + _viewController = viewController; + } + return self; +} + +- (void)presentViewController:(UIViewController *)viewControllerToPresent + animated:(BOOL)flag + completion:(nullable void (^)(void))completion { + [_viewController presentViewController:viewControllerToPresent + animated:flag + completion:completion]; +} + +- (void)dismissViewControllerAnimated:(BOOL)flag completion:(nullable void (^)(void))completion { + [_viewController dismissViewControllerAnimated:flag completion:completion]; +} + ++ (id)defaultUIDelegate { + // iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication + // responds to it. + static Class applicationClass = nil; + if (![GULAppEnvironmentUtil isAppExtension]) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + + UIViewController *topViewController; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13.0, tvOS 13.0, *)) { + UIApplication *application = [applicationClass sharedApplication]; + NSSet *connectedScenes = application.connectedScenes; + for (UIScene *scene in connectedScenes) { + if ([scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *windowScene = (UIWindowScene *)scene; + for (UIWindow *window in windowScene.windows) { + if (window.isKeyWindow) { + topViewController = window.rootViewController; + } + } + } + } + } else { + UIApplication *application = [applicationClass sharedApplication]; +// iOS 13 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + topViewController = application.keyWindow.rootViewController; +#pragma clang diagnostic pop + } +#else + UIApplication *application = [applicationClass sharedApplication]; + topViewController = application.keyWindow.rootViewController; +#endif + + while (true) { + if (topViewController.presentedViewController) { + topViewController = topViewController.presentedViewController; + } else if ([topViewController isKindOfClass:[UINavigationController class]]) { + UINavigationController *nav = (UINavigationController *)topViewController; + topViewController = nav.topViewController; + } else if ([topViewController isKindOfClass:[UITabBarController class]]) { + UITabBarController *tab = (UITabBarController *)topViewController; + topViewController = tab.selectedViewController; + } else { + break; + } + } + return [[FIRAuthDefaultUIDelegate alloc] initWithViewController:topViewController]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h new file mode 100644 index 00000000..1ee020c7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h @@ -0,0 +1,585 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h" + +@class FIRAuthCredential; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthErrorUtils + @brief Utility class used to construct @c NSError instances. + */ +@interface FIRAuthErrorUtils : NSObject + ++ (NSError *)errorWithCode:(FIRAuthInternalErrorCode)code message:(nullable NSString *)message; + +/** @fn RPCRequestEncodingErrorWithUnderlyingError + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeRPCRequestEncodingError + code and a populated @c NSUnderlyingErrorKey in the @c NSError.userInfo dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey key. + @remarks This error is used when an @c FIRAuthRPCRequest.unencodedHTTPRequestBodyWithError: + invocation returns an error. The error returned is wrapped in this internal error code. + */ ++ (NSError *)RPCRequestEncodingErrorWithUnderlyingError:(NSError *)underlyingError; + +/** @fn JSONSerializationErrorForUnencodableType + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeJSONSerializationError code. + @remarks This error is used when an @c NSJSONSerialization.isValidJSONObject: check fails, not + for when an error is returned from @c NSJSONSerialization.dataWithJSONObject:options:error:. + */ ++ (NSError *)JSONSerializationErrorForUnencodableType; + +/** @fn JSONSerializationErrorWithUnderlyingError: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeJSONSerializationError code, and the + @c underlyingError as the @c NSUnderlyingErrorKey value in the @c NSError.userInfo + dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey key. + @remarks This error is used when an invocation of + @c NSJSONSerialization.dataWithJSONObject:options:error: returns an error. + */ ++ (NSError *)JSONSerializationErrorWithUnderlyingError:(NSError *)underlyingError; + +/** @fn networkErrorWithUnderlyingError: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeNetworkError code, and the + @c underlyingError as the @c NSUnderlyingErrorKey value in the @c NSError.userInfo + dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey key. Should be the error from + GTM. + @remarks This error is used when a network request results in an error, and no body data was + returned. + */ ++ (NSError *)networkErrorWithUnderlyingError:(NSError *)underlyingError; + +/** @fn unexpectedErrorResponseWithUnderlyingError: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeNetworkError code, and the + @c underlyingError as the @c NSUnderlyingErrorKey value. + @param data The value of the @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo + dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey key in the @c NSError.userInfo + dictionary. + @remarks This error is used when a network request results in an error, and unserializable body + data was returned. + */ ++ (NSError *)unexpectedErrorResponseWithData:(NSData *)data + underlyingError:(NSError *)underlyingError; + +/** @fn unexpectedErrorResponseWithDeserializedResponse: + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedErrorResponse + code, and a populated @c FIRAuthErrorUserInfoDeserializedResponseKey key in the + @c NSError.userInfo dictionary. + @param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key. + @remarks This error is used when a network request results in an error, and the body data was + deserializable as JSON, but couldn't be decoded as an error. + */ ++ (NSError *)unexpectedErrorResponseWithDeserializedResponse:(id)deserializedResponse; + +/** @fn malformedJWTErrorWithToken:underlyingError: + @brief Constructs an @c NSError with the code set to @c FIRAuthErrorCodeMalformedJWT and + populates the userInfo dictionary with an error message, the bad token, and an underlying + error that may have occurred when parsing. + @param token The token that failed to parse. + @param underlyingError The error that caused this error. If this parameter is nil, the + NSUnderlyingErrorKey value will not be set. + @remarks This error is returned when JWT parsing fails. + @returns An @c FIRAuthErrorCodeMalformedJWT error wrapping an underlying error, if available. + */ ++ (NSError *)malformedJWTErrorWithToken:(NSString *)token + underlyingError:(NSError *_Nullable)underlyingError; + +/** @fn unexpectedResponseWithData:underlyingError: + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse + code, and a populated @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo + dictionary. + @param data The value of the @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo + dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey key in the @c NSError.userInfo + dictionary. + @remarks This error is used when a network request is apparently successful, but the body data + couldn't be deserialized as JSON. + */ ++ (NSError *)unexpectedResponseWithData:(NSData *)data underlyingError:(NSError *)underlyingError; +; + +/** @fn unexpectedResponseWithDeserializedResponse: + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse + code, and a populated @c FIRAuthErrorUserInfoDeserializedResponseKey key in the + @c NSError.userInfo dictionary. + @param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key. + @remarks This error is used when a network request is apparently successful, the body data was + successfully deserialized as JSON, but the JSON wasn't a dictionary. + */ ++ (NSError *)unexpectedResponseWithDeserializedResponse:(id)deserializedResponse; + +/** @fn unexpectedResponseWithDeserializedResponse:underlyingError: + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse + code, and populated @c FIRAuthErrorUserInfoDeserializedResponseKey and + @c NSUnderlyingErrorKey keys in the @c NSError.userInfo dictionary. + @param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key. + @param underlyingError The value of the @c NSUnderlyingErrorKey key. + @remarks This error is used when a network request was apparently successful, the body data was + successfully deserialized as JSON, but the data type of the response was unexpected. + */ ++ (NSError *)unexpectedResponseWithDeserializedResponse:(nullable id)deserializedResponse + underlyingError:(NSError *)underlyingError; + +/** @fn RPCResponseDecodingErrorWithDeserializedResponse:underlyingError: + @brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeRPCResponseDecodingError + code, and populated @c FIRAuthErrorUserInfoDeserializedResponseKey and + @c NSUnderlyingErrorKey keys in the @c NSError.userInfo dictionary. + @param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key. + @param underlyingError The value of the @c NSUnderlyingErrorKey key. + @remarks This error is used when an invocation of @c FIRAuthRPCResponse.setWithDictionary:error: + resulted in an error. + */ ++ (NSError *)RPCResponseDecodingErrorWithDeserializedResponse:(id)deserializedResponse + underlyingError:(NSError *)underlyingError; + +/** @fn emailAlreadyInUseErrorWithEmail: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeEmailExists code. + @param email The email address that is already in use. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)emailAlreadyInUseErrorWithEmail:(nullable NSString *)email; + +/** @fn userDisabledErrorWithMessageWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserDisabled code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)userDisabledErrorWithMessage:(nullable NSString *)message; + +/** @fn wrongPasswordErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeWrongPassword code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)wrongPasswordErrorWithMessage:(nullable NSString *)message; + +/** @fn tooManyRequestsErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeTooManyRequests Code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)tooManyRequestsErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidCustomTokenErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidCustomToken code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidCustomTokenErrorWithMessage:(nullable NSString *)message; + +/** @fn customTokenMistmatchErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeCustomTokenMismatch code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)customTokenMistmatchErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidCredentialErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidCredential code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidCredentialErrorWithMessage:(nullable NSString *)message; + +/** @fn requiresRecentLoginError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeRequiresRecentLogin code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)requiresRecentLoginErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidUserTokenErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidUserToken code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidUserTokenErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidEmailErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidEmail code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidEmailErrorWithMessage:(nullable NSString *)message; + +/** @fn accountExistsWithDifferentCredentialErrorWithEmail: + @brief Constructs an @c NSError with the @c FIRAuthErrorAccountExistsWithDifferentCredential + code. + @param email The email address that is already associated with an existing account + @param updatedCredential The updated credential for the existing account + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)accountExistsWithDifferentCredentialErrorWithEmail:(nullable NSString *)email + updatedCredential: + (nullable FIRAuthCredential *)updatedCredential; + +/** @fn providerAlreadyLinkedErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeProviderAlreadyLinked code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)providerAlreadyLinkedError; + +/** @fn noSuchProviderError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeNoSuchProvider code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)noSuchProviderError; + +/** @fn userTokenExpiredErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserTokenExpired code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)userTokenExpiredErrorWithMessage:(nullable NSString *)message; + +/** @fn userNotFoundErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserNotFound code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)userNotFoundErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidLocalAPIKeyErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidAPIKey code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidAPIKeyError; + +/** @fn userMismatchError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserMismatch code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)userMismatchError; + +/** @fn credentialAlreadyInUseErrorWithMessage:email: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeCredentialAlreadyInUse code. + @param message Error message from the backend, if any. + @param credential Auth credential to be added to the Error User Info dictionary. + @param email Email to be added to the Error User Info dictionary. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)credentialAlreadyInUseErrorWithMessage:(nullable NSString *)message + credential:(nullable FIRAuthCredential *)credential + email:(nullable NSString *)email; +/** @fn operationNotAllowedErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeOperationNotAllowed code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)operationNotAllowedErrorWithMessage:(nullable NSString *)message; + +/** @fn weakPasswordErrorWithServerResponseReason: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeWeakPassword code. + @param serverResponseReason A more detailed explanation string from server response. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)weakPasswordErrorWithServerResponseReason:(nullable NSString *)serverResponseReason; + +/** @fn appNotAuthorizedError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeAppNotAuthorized code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)appNotAuthorizedError; + +/** @fn expiredActionCodeErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeExpiredActionCode code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)expiredActionCodeErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidActionCodeErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidActionCode code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidActionCodeErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidMessagePayloadError: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidMessagePayload code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidMessagePayloadErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidSenderErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidSender code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidSenderErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidRecipientEmailError: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidRecipientEmail code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidRecipientEmailErrorWithMessage:(nullable NSString *)message; + +/** @fn missingIosBundleIDErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingIosBundleID code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingIosBundleIDErrorWithMessage:(nullable NSString *)message; + +/** @fn missingAndroidPackageNameErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingAndroidPackageName code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingAndroidPackageNameErrorWithMessage:(nullable NSString *)message; + +/** @fn unauthorizedDomainErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeUnauthorizedDomain code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)unauthorizedDomainErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidContinueURIErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidContinueURI code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidContinueURIErrorWithMessage:(nullable NSString *)message; + +/** @fn missingContinueURIErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingContinueURI code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingContinueURIErrorWithMessage:(nullable NSString *)message; + +/** @fn missingEmailErrorWithMessage + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingEmail code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingEmailErrorWithMessage:(nullable NSString *)message; + +/** @fn missingPhoneNumberErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingPhoneNumber code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingPhoneNumberErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidPhoneNumberErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidPhoneNumber code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidPhoneNumberErrorWithMessage:(nullable NSString *)message; + +/** @fn missingVerificationCodeErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingVerificationCode code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingVerificationCodeErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidVerificationCodeErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidVerificationCode code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidVerificationCodeErrorWithMessage:(nullable NSString *)message; + +/** @fn missingVerificationIDErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingVerificationID code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingVerificationIDErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidVerificationIDErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidVerificationID code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidVerificationIDErrorWithMessage:(nullable NSString *)message; + +/** @fn sessionExpiredErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeSessionExpired code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)sessionExpiredErrorWithMessage:(nullable NSString *)message; + +/** @fn missingAppCredentialWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorMissingCredential code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingAppCredentialWithMessage:(nullable NSString *)message; + +/** @fn invalidAppCredentialWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorInvalidCredential code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)invalidAppCredentialWithMessage:(nullable NSString *)message; + +/** @fn quotaExceededErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeQuotaExceeded code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)quotaExceededErrorWithMessage:(nullable NSString *)message; + +/** @fn missingAppTokenErrorWithUnderlyingError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingAppToken code. + @param underlyingError The underlying error, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingAppTokenErrorWithUnderlyingError:(nullable NSError *)underlyingError; + +/** @fn localPlayerNotAuthenticatedError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeLocalPlayerNotAuthenticated code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)localPlayerNotAuthenticatedError; + +/** @fn gameKitNotLinkedError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeGameKitNotLinked code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)gameKitNotLinkedError; + +/** @fn notificationNotForwardedError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeNotificationNotForwarded code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)notificationNotForwardedError; + +#if TARGET_OS_IOS +/** @fn secondFactorRequiredError + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeSecondFactorRequired code. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)secondFactorRequiredErrorWithPendingCredential:(NSString *)MFAPendingCredential + hints:(NSArray *) + multiFactorInfo; +#endif + +/** @fn appNotVerifiedErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeAppNotVerified code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)appNotVerifiedErrorWithMessage:(nullable NSString *)message; + +/** @fn missingClientIdentifierErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingClientIdentifier code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)missingClientIdentifierErrorWithMessage:(nullable NSString *)message; + +/** @fn captchaCheckFailedErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCaptchaCheckFailed code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)captchaCheckFailedErrorWithMessage:(nullable NSString *)message; + +/** @fn webContextAlreadyPresentedErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeWebContextAlreadyPresented code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)webContextAlreadyPresentedErrorWithMessage:(nullable NSString *)message; + +/** @fn webContextCancelledErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeWebContextCancelled code. + @param message Error message from the backend, if any. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)webContextCancelledErrorWithMessage:(nullable NSString *)message; + +/** @fn appVerificationUserInteractionFailureWithReason: + @brief Constructs an @c NSError with the @c + FIRAuthErrorCodeAppVerificationUserInteractionFailure code. + @param reason Reason for error, returned via URL response. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)appVerificationUserInteractionFailureWithReason:(NSString *)reason; + +/** @fn webSignInUserInteractionFailureWithReason: + @brief Constructs an @c NSError with the @c + FIRAuthErrorCodeWebSignInUserInteractionFailure code. + @param reason Reason for error, returned via URL response. + @return The NSError instance associated with the given FIRAuthError. + */ ++ (NSError *)webSignInUserInteractionFailureWithReason:(nullable NSString *)reason; + +/** @fn URLResponseErrorWithCode:message: + @brief Constructs an @c NSError with the code and message provided. + @param message Error message from the backend, if any. + @return The nullable NSError instance associated with the given error message, if one is found. + */ ++ (nullable NSError *)URLResponseErrorWithCode:(NSString *)code + message:(nullable NSString *)message; + +/** @fn nullUserErrorWithMessage: + @brief Constructs an @c NSError with the code and message provided. + @param message Error message from the backend, if any. + @return The nullable NSError instance associated with the given error message, if one is found. + */ ++ (NSError *)nullUserErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidProviderIDErrorWithMessage: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidProviderID code. + @param message Error message from the backend, if any. + @remarks This error indicates that the provider id given for the web operation is invalid. + */ ++ (NSError *)invalidProviderIDErrorWithMessage:(nullable NSString *)message; + +/** @fn invalidDynamicLinkDomainErrorWithMessage: + @brief Constructs an @c NSError with the code and message provided. + @param message Error message from the backend, if any. + @return The nullable NSError instance associated with the given error message, if one is found. + */ ++ (NSError *)invalidDynamicLinkDomainErrorWithMessage:(nullable NSString *)message; + +/** @fn keychainErrorWithFunction:status: + @brief Constructs an @c NSError with the @c FIRAuthErrorCodeKeychainError code. + @param keychainFunction The keychain function which was invoked and yielded an unexpected + response. The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo + dictionary will contain a string partially comprised of this value. + @param status The response status from the invoked keychain function. The + @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo dictionary will contain + a string partially comprised of this value. + */ ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status; + +/** @fn missingOrInvalidNonceErrorWithMessage: + @brief Constructs an @c NSError with the code and message provided. + @param message Error message from the backend, if any. + @return The nullable NSError instance associated with the given error message, if one is found. +*/ ++ (NSError *)missingOrInvalidNonceErrorWithMessage:(nullable NSString *)message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m new file mode 100644 index 00000000..142c36b3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m @@ -0,0 +1,1368 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +#import + +#import "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +NSString *const FIRAuthErrorDomain = @"FIRAuthErrorDomain"; + +NSString *const FIRAuthInternalErrorDomain = @"FIRAuthInternalErrorDomain"; + +NSString *const FIRAuthErrorUserInfoDeserializedResponseKey = + @"FIRAuthErrorUserInfoDeserializedResponseKey"; + +NSString *const FIRAuthErrorUserInfoDataKey = @"FIRAuthErrorUserInfoDataKey"; + +NSString *const FIRAuthErrorUserInfoEmailKey = @"FIRAuthErrorUserInfoEmailKey"; + +NSString *const FIRAuthErrorUserInfoUpdatedCredentialKey = + @"FIRAuthErrorUserInfoUpdatedCredentialKey"; + +NSString *const FIRAuthErrorUserInfoNameKey = @"FIRAuthErrorUserInfoNameKey"; + +NSString *const FIRAuthErrorUserInfoMultiFactorResolverKey = + @"FIRAuthErrorUserInfoMultiFactorResolverKey"; + +/** @var kServerErrorDetailMarker + @brief This marker indicates that the server error message contains a detail error message which + should be used instead of the hardcoded client error message. + */ +static NSString *const kServerErrorDetailMarker = @" : "; + +#pragma mark - URL response error codes + +/** @var kURLResponseErrorCodeInvalidClientID + @brief Error code that indicates that the client ID provided was invalid. + */ +static NSString *const kURLResponseErrorCodeInvalidClientID = @"auth/invalid-oauth-client-id"; + +/** @var kURLResponseErrorCodeNetworkRequestFailed + @brief Error code that indicates that a network request within the SFSafariViewController or + WKWebView failed. + */ +static NSString *const kURLResponseErrorCodeNetworkRequestFailed = @"auth/network-request-failed"; + +/** @var kURLResponseErrorCodeInternalError + @brief Error code that indicates that an internal error occurred within the + SFSafariViewController or WKWebView failed. + */ +static NSString *const kURLResponseErrorCodeInternalError = @"auth/internal-error"; + +#pragma mark - Standard Error Messages + +/** @var kFIRAuthErrorMessageInvalidCustomToken + @brief Message for @c FIRAuthErrorCodeInvalidCustomToken error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidCustomToken = + @"The custom token format is " + "incorrect. Please check the documentation."; + +/** @var kFIRAuthErrorMessageCustomTokenMismatch + @brief Message for @c FIRAuthErrorCodeCustomTokenMismatch error code. + */ +static NSString *const kFIRAuthErrorMessageCustomTokenMismatch = @"The custom token corresponds to " + "a different audience."; + +/** @var kFIRAuthErrorMessageInvalidEmail + @brief Message for @c FIRAuthErrorCodeInvalidEmail error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidEmail = @"The email address is badly formatted."; + +/** @var kFIRAuthErrorMessageInvalidCredential + @brief Message for @c FIRAuthErrorCodeInvalidCredential error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidCredential = @"The supplied auth credential is " + "malformed or has expired."; + +/** @var kFIRAuthErrorMessageUserDisabled + @brief Message for @c FIRAuthErrorCodeUserDisabled error code. + */ +static NSString *const kFIRAuthErrorMessageUserDisabled = @"The user account has been disabled by " + "an administrator."; + +/** @var kFIRAuthErrorMessageEmailAlreadyInUse + @brief Message for @c FIRAuthErrorCodeEmailAlreadyInUse error code. + */ +static NSString *const kFIRAuthErrorMessageEmailAlreadyInUse = @"The email address is already in " + "use by another account."; + +/** @var kFIRAuthErrorMessageWrongPassword + @brief Message for @c FIRAuthErrorCodeWrongPassword error code. + */ +static NSString *const kFIRAuthErrorMessageWrongPassword = @"The password is invalid or the user " + "does not have a password."; + +/** @var kFIRAuthErrorMessageTooManyRequests + @brief Message for @c FIRAuthErrorCodeTooManyRequests error code. + */ +static NSString *const kFIRAuthErrorMessageTooManyRequests = + @"We have blocked all requests from " + "this device due to unusual activity. Try again later."; + +/** @var kFIRAuthErrorMessageAccountExistsWithDifferentCredential + @brief Message for @c FIRAuthErrorCodeAccountExistsWithDifferentCredential error code. + */ +static NSString *const kFIRAuthErrorMessageAccountExistsWithDifferentCredential = + @"An account " + "already exists with the same email address but different sign-in credentials. Sign in using " + "a " + "provider associated with this email address."; + +/** @var kFIRAuthErrorMessageRequiresRecentLogin + @brief Message for @c FIRAuthErrorCodeRequiresRecentLogin error code. + */ +static NSString *const kFIRAuthErrorMessageRequiresRecentLogin = + @"This operation is sensitive and " + "requires recent authentication. Log in again before retrying this request."; + +/** @var kFIRAuthErrorMessageProviderAlreadyLinked + @brief Message for @c FIRAuthErrorCodeProviderAlreadyExists error code. + */ +static NSString *const kFIRAuthErrorMessageProviderAlreadyLinked = + @"[ERROR_PROVIDER_ALREADY_LINKED] - User can only be linked to one identity for the given " + "provider."; + +/** @var kFIRAuthErrorMessageNoSuchProvider + @brief Message for @c FIRAuthErrorCodeNoSuchProvider error code. + */ +static NSString *const kFIRAuthErrorMessageNoSuchProvider = @"User was not linked to an account " + "with the given provider."; + +/** @var kFIRAuthErrorMessageInvalidUserToken + @brief Message for @c FIRAuthErrorCodeInvalidUserToken error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidUserToken = + @"This user's credential isn't valid " + "for this project. This can happen if the user's token has been tampered with, or if the user " + "doesn’t belong to the project associated with the API key used in your request."; + +/** @var kFIRAuthErrorMessageNetworkError + @brief Message for @c FIRAuthErrorCodeNetworkError error code. + */ +static NSString *const kFIRAuthErrorMessageNetworkError = + @"Network error (such as timeout, " + "interrupted connection or unreachable host) has occurred."; + +/** @var kFIRAuthErrorMessageKeychainError + @brief Message for @c FIRAuthErrorCodeKeychainError error code. + */ +static NSString *const kFIRAuthErrorMessageKeychainError = + @"An error occurred when accessing the " + "keychain. The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo " + "dictionary " + "will contain more information about the error encountered"; + +/** @var kFIRAuthErrorMessageMissingClientIdentifier + @brief Message for @c FIRAuthErrorCodeMissingClientIdentifier error code. + */ +static NSString *const kFIRAuthErrorMessageMissingClientIdentifier = + @"The request does not contain " + "any client identifier."; + +/** @var kFIRAuthErrorMessageUserTokenExpired + @brief Message for @c FIRAuthErrorCodeTokenExpired error code. + */ +static NSString *const kFIRAuthErrorMessageUserTokenExpired = + @"The user's credential is no longer " + "valid. The user must sign in again."; + +/** @var kFIRAuthErrorMessageUserNotFound + @brief Message for @c FIRAuthErrorCodeUserNotFound error code. + */ +static NSString *const kFIRAuthErrorMessageUserNotFound = + @"There is no user record corresponding " + "to this identifier. The user may have been deleted."; + +/** @var kFIRAuthErrorMessageInvalidAPIKey + @brief Message for @c FIRAuthErrorCodeInvalidAPIKey error code. + @remarks This error is not thrown by the server. + */ +static NSString *const kFIRAuthErrorMessageInvalidAPIKey = @"An invalid API Key was supplied in " + "the request."; + +/** @var kFIRAuthErrorMessageUserMismatch. + @brief Message for @c FIRAuthErrorCodeInvalidAPIKey error code. + */ +static NSString *const FIRAuthErrorMessageUserMismatch = + @"The supplied credentials do not " + "correspond to the previously signed in user."; + +/** @var kFIRAuthErrorMessageCredentialAlreadyInUse + @brief Message for @c FIRAuthErrorCodeCredentialAlreadyInUse error code. + */ +static NSString *const kFIRAuthErrorMessageCredentialAlreadyInUse = + @"This credential is already " + "associated with a different user account."; + +/** @var kFIRAuthErrorMessageOperationNotAllowed + @brief Message for @c FIRAuthErrorCodeOperationNotAllowed error code. + */ +static NSString *const kFIRAuthErrorMessageOperationNotAllowed = + @"The given sign-in provider is " + "disabled for this Firebase project. Enable it in the Firebase console, under the sign-in " + "method tab of the Auth section."; + +/** @var kFIRAuthErrorMessageWeakPassword + @brief Message for @c FIRAuthErrorCodeWeakPassword error code. + */ +static NSString *const kFIRAuthErrorMessageWeakPassword = @"The password must be 6 characters long " + "or more."; + +/** @var kFIRAuthErrorMessageAppNotAuthorized + @brief Message for @c FIRAuthErrorCodeAppNotAuthorized error code. + */ +static NSString *const kFIRAuthErrorMessageAppNotAuthorized = + @"This app is not authorized to use " + "Firebase Authentication with the provided API key. Review your key configuration in the " + "Google API console and ensure that it accepts requests from your app's bundle ID."; + +/** @var kFIRAuthErrorMessageExpiredActionCode + @brief Message for @c FIRAuthErrorCodeExpiredActionCode error code. + */ +static NSString *const kFIRAuthErrorMessageExpiredActionCode = @"The action code has expired."; + +/** @var kFIRAuthErrorMessageInvalidActionCode + @brief Message for @c FIRAuthErrorCodeInvalidActionCode error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidActionCode = + @"The action code is invalid. This " + "can happen if the code is malformed, expired, or has already been used."; + +/** @var kFIRAuthErrorMessageInvalidMessagePayload + @brief Message for @c FIRAuthErrorCodeInvalidMessagePayload error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidMessagePayload = + @"The action code is invalid. " + "This can happen if the code is malformed, expired, or has already been used."; + +/** @var kFIRAuthErrorMessageInvalidSender + @brief Message for @c FIRAuthErrorCodeInvalidSender error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidSender = + @"The email template corresponding to " + "this action contains invalid characters in its message. Please fix by going to the Auth " + "email " + "templates section in the Firebase Console."; + +/** @var kFIRAuthErrorMessageInvalidRecipientEmail + @brief Message for @c FIRAuthErrorCodeInvalidRecipient error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidRecipientEmail = + @"The action code is invalid. " + "This can happen if the code is malformed, expired, or has already been used."; + +/** @var kFIRAuthErrorMessageMissingIosBundleID + @brief Message for @c FIRAuthErrorCodeMissingIosbundleID error code. + */ +static NSString *const kFIRAuthErrorMessageMissingIosBundleID = + @"An iOS Bundle ID must be provided if an App Store ID is provided."; + +/** @var kFIRAuthErrorMessageMissingAndroidPackageName + @brief Message for @c FIRAuthErrorCodeMissingAndroidPackageName error code. + */ +static NSString *const kFIRAuthErrorMessageMissingAndroidPackageName = + @"An Android Package Name must be provided if the Android App is required to be installed."; + +/** @var kFIRAuthErrorMessageUnauthorizedDomain + @brief Message for @c FIRAuthErrorCodeUnauthorizedDomain error code. + */ +static NSString *const kFIRAuthErrorMessageUnauthorizedDomain = + @"The domain of the continue URL " + "is not whitelisted. Please whitelist the domain in the Firebase console."; + +/** @var kFIRAuthErrorMessageInvalidContinueURI + @brief Message for @c FIRAuthErrorCodeInvalidContinueURI error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidContinueURI = + @"The continue URL provided in the request is invalid."; + +/** @var kFIRAuthErrorMessageMissingEmail + @brief Message for @c FIRAuthErrorCodeMissingEmail error code. + */ +static NSString *const kFIRAuthErrorMessageMissingEmail = @"An email address must be provided."; + +/** @var kFIRAuthErrorMessageMissingContinueURI + @brief Message for @c FIRAuthErrorCodeMissingContinueURI error code. + */ +static NSString *const kFIRAuthErrorMessageMissingContinueURI = + @"A continue URL must be provided in the request."; + +/** @var kFIRAuthErrorMessageMissingPhoneNumber + @brief Message for @c FIRAuthErrorCodeMissingPhoneNumber error code. + */ +static NSString *const kFIRAuthErrorMessageMissingPhoneNumber = + @"To send verification codes, provide a phone number for the recipient."; + +/** @var kFIRAuthErrorMessageInvalidPhoneNumber + @brief Message for @c FIRAuthErrorCodeInvalidPhoneNumber error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidPhoneNumber = + @"The format of the phone number provided is incorrect. Please enter the phone number in a " + "format that can be parsed into E.164 format. E.164 phone numbers are written in the format " + "[+][country code][subscriber number including area code]."; + +/** @var kFIRAuthErrorMessageMissingVerificationCode + @brief Message for @c FIRAuthErrorCodeMissingVerificationCode error code. + */ +static NSString *const kFIRAuthErrorMessageMissingVerificationCode = + @"The phone auth credential was created with an empty SMS verification Code."; + +/** @var kFIRAuthErrorMessageInvalidVerificationCode + @brief Message for @c FIRAuthErrorCodeInvalidVerificationCode error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidVerificationCode = + @"The SMS verification code used to create the phone auth credential is invalid. Please resend " + "the verification code SMS and be sure to use the verification code provided by the user."; + +/** @var kFIRAuthErrorMessageMissingVerificationID + @brief Message for @c FIRAuthErrorCodeInvalidVerificationID error code. + */ +static NSString *const kFIRAuthErrorMessageMissingVerificationID = + @"The phone auth credential was created with an empty verification ID."; + +/** @var kFIRAuthErrorMessageInvalidVerificationID + @brief Message for @c FIRAuthErrorCodeInvalidVerificationID error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidVerificationID = + @"The verification ID used to create the phone auth credential is invalid."; + +/** @var kFIRAuthErrorMessageLocalPlayerNotAuthenticated + @brief Message for @c FIRAuthErrorCodeLocalPlayerNotAuthenticated error code. + */ +static NSString *const kFIRAuthErrorMessageLocalPlayerNotAuthenticated = + @"The local player is not authenticated. Please log the local player in to Game Center."; + +/** @var kFIRAuthErrorMessageGameKitNotLinked + @brief Message for @c kFIRAuthErrorMessageGameKitNotLinked error code. + */ +static NSString *const kFIRAuthErrorMessageGameKitNotLinked = + @"The GameKit framework is not linked. Please turn on the Game Center capability."; + +/** @var kFIRAuthErrorMessageSessionExpired + @brief Message for @c FIRAuthErrorCodeSessionExpired error code. + */ +static NSString *const kFIRAuthErrorMessageSessionExpired = + @"The SMS code has expired. Please " + @"re-send the verification code to try again."; + +/** @var kFIRAuthErrorMessageMissingAppCredential + @brief Message for @c FIRAuthErrorCodeMissingAppCredential error code. + */ +static NSString *const kFIRAuthErrorMessageMissingAppCredential = + @"The phone verification request " + "is missing an APNs Device token. Firebase Auth automatically detects APNs Device Tokens, " + "however, if method swizzling is disabled, the APNs token must be set via the APNSToken " + "property on FIRAuth or by calling setAPNSToken:type on FIRAuth."; + +/** @var kFIRAuthErrorMessageInvalidAppCredential + @brief Message for @c FIRAuthErrorCodeInvalidAppCredential error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidAppCredential = + @"The APNs device token provided " + "is either incorrect or does not match the private certificate uploaded to the Firebase " + "Console."; + +/** @var kFIRAuthErrorMessageQuotaExceeded + @brief Message for @c FIRAuthErrorCodeQuotaExceeded error code. + */ +static NSString *const kFIRAuthErrorMessageQuotaExceeded = @"The quota for this operation " + "has been exceeded."; + +/** @var kFIRAuthErrorMessageMissingAppToken + @brief Message for @c FIRAuthErrorCodeMissingAppToken error code. + */ +static NSString *const kFIRAuthErrorMessageMissingAppToken = + @"There seems to be a problem with " + "your project's Firebase phone number authentication set-up, please make sure to follow the " + "instructions found at https://firebase.google.com/docs/auth/ios/phone-auth"; + +/** @var kFIRAuthErrorMessageMissingAppToken + @brief Message for @c FIRAuthErrorCodeMissingAppToken error code. + */ +static NSString *const kFIRAuthErrorMessageNotificationNotForwarded = + @"If app delegate swizzling " + "is disabled, remote notifications received by UIApplicationDelegate need to be forwarded to " + "FIRAuth's canHandleNotificaton: method."; + +/** @var kFIRAuthErrorMessageAppNotVerified + @brief Message for @c FIRAuthErrorCodeMissingAppToken error code. + */ +static NSString *const kFIRAuthErrorMessageAppNotVerified = + @"Firebase could not retrieve the " + "silent push notification and therefore could not verify your app. Ensure that you configured " + "your app correctly to receive push notifications."; + +/** @var kFIRAuthErrorMessageCaptchaCheckFailed + @brief Message for @c FIRAuthErrorCodeCaptchaCheckFailed error code. + */ +static NSString *const kFIRAuthErrorMessageCaptchaCheckFailed = + @"The reCAPTCHA response token " + "provided is either invalid, expired or already"; + +/** @var kFIRAuthErrorMessageWebContextAlreadyPresented + @brief Message for @c FIRAuthErrorCodeWebContextAlreadyPresented error code. + */ +static NSString *const kFIRAuthErrorMessageWebContextAlreadyPresented = + @"User interaction is " + "still ongoing, another view cannot be presented."; + +/** @var kFIRAuthErrorMessageWebContextCancelled + @brief Message for @c FIRAuthErrorCodeWebContextCancelled error code. + */ +static NSString *const kFIRAuthErrorMessageWebContextCancelled = @"The interaction was cancelled " + "by the user."; + +/** @var kFIRAuthErrorMessageInvalidClientID + @brief Message for @c FIRAuthErrorCodeInvalidClientID error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidClientID = + @"The OAuth client ID provided is " + "either invalid or does not match the specified API key."; + +/** @var kFIRAuthErrorMessageWebRequestFailed + @brief Message for @c FIRAuthErrorCodeWebRequestFailed error code. + */ +static NSString *const kFIRAuthErrorMessageWebRequestFailed = + @"A network error (such as timeout, " + "interrupted connection, or unreachable host) has occurred within the web context."; + +/** @var kFIRAuthErrorMessageWebInternalError + @brief Message for @c FIRAuthErrorCodeWebInternalError error code. + */ +static NSString *const kFIRAuthErrorMessageWebInternalError = + @"An internal error has occurred " + "within the SFSafariViewController or WKWebView."; + +/** @var kFIRAuthErrorMessageAppVerificationUserInteractionFailure + @brief Message for @c FIRAuthErrorCodeInvalidClientID error code. + */ +static NSString *const kFIRAuthErrorMessageAppVerificationUserInteractionFailure = + @"The app " + "verification process has failed, print and inspect the error details for more information"; + +/** @var kFIRAuthErrorMessageNullUser + @brief Message for @c FIRAuthErrorCodeNullUser error code. + */ +static NSString *const kFIRAuthErrorMessageNullUser = + @"A null user object was provided as the " + "argument for an operation which requires a non-null user object."; + +/** @var kFIRAuthErrorMessageInvalidProviderID + @brief Message for @c FIRAuthErrorCodeInvalidProviderID error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidProviderID = + @"The provider ID provided for the " + "attempted web operation is invalid."; + +/** @var kFIRAuthErrorMessageInvalidDynamicLinkDomain + @brief Message for @c kFIRAuthErrorMessageInvalidDynamicLinkDomain error code. + */ +static NSString *const kFIRAuthErrorMessageInvalidDynamicLinkDomain = + @"The " + "Firebase Dynamic Link domain used is either not configured or is unauthorized " + "for the current project."; + +/** @var kFIRAuthErrorMessageInternalError + @brief Message for @c FIRAuthErrorCodeInternalError error code. + */ +static NSString *const kFIRAuthErrorMessageInternalError = + @"An internal error has occurred, " + "print and inspect the error details for more information."; + +/** @var kFIRAuthErrorMessageMalformedJWT + @brief Error message constant describing @c FIRAuthErrorCodeMalformedJWT errors. + */ +static NSString *const kFIRAuthErrorMessageMalformedJWT = + @"Failed to parse JWT. Check the userInfo dictionary for the full token."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const kFIRAuthErrorMessageSecondFactorRequired = + @"Please complete a second factor challenge to finish signing into this account."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageMissingMultiFactorSession = + @"The request is missing proof of first factor successful sign-in."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageMissingMultiFactorInfo = + @"No second factor identifier is provided."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageInvalidMultiFactorSession = + @"The request does not contain a valid proof of first factor successful sign-in."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageMultiFactorInfoNotFound = + @"The user does not have a second factor matching the identifier provided."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageAdminRestrictedOperation = + @"This operation is restricted to administrators only."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageUnverifiedEmail = + @"The operation requires a verified email."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageSecondFactorAlreadyEnrolled = + @"The second factor is already enrolled on this account."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageMaximumSecondFactorCountExceeded = + @"The maximum allowed number of second factors on a user has been exceeded."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageUnsupportedFirstFactor = + @"Enrolling a second factor or signing in with a multi-factor account requires sign-in with a " + @"supported first factor."; + +/** @var kFIRAuthErrorMessageSecondFactorRequired + @brief Message for @c kFIRAuthErrorMessageSecondFactorRequired error code. + */ +static NSString *const FIRAuthErrorMessageEmailChangeNeedsVerification = + @"Multi-factor users must always have a verified email."; + +/** @var kFIRAuthErrorMessageDynamicLinkNotActivated + @brief Error message constant describing @c FIRAuthErrorCodeDynamicLinkNotActivated errors. + */ +static NSString *const kFIRAuthErrorMessageDynamicLinkNotActivated = + @"Please activate Dynamic Links in the Firebase Console and agree to the terms and conditions."; + +/** @var kFIRAuthErrorMessageRejectedCredential + @brief Error message constant describing @c FIRAuthErrorCodeRejectedCredential errors. + */ +static NSString *const kFIRAuthErrorMessageRejectedCredential = + @"The request contains malformed or mismatching credentials."; + +/** @var kFIRAuthErrorMessageMissingOrInvalidNonce + @brief Error message constant describing @c FIRAuthErrorCodeMissingOrInvalidNonce errors. + */ +static NSString *const kFIRAuthErrorMessageMissingOrInvalidNonce = + @"The request contains malformed or mismatched credentials."; + +/** @var FIRAuthErrorDescription + @brief The error descrioption, based on the error code. + @remarks No default case so that we get a compiler warning if a new value was added to the enum. + */ +static NSString *FIRAuthErrorDescription(FIRAuthErrorCode code) { + switch (code) { + case FIRAuthErrorCodeInvalidCustomToken: + return kFIRAuthErrorMessageInvalidCustomToken; + case FIRAuthErrorCodeCustomTokenMismatch: + return kFIRAuthErrorMessageCustomTokenMismatch; + case FIRAuthErrorCodeInvalidEmail: + return kFIRAuthErrorMessageInvalidEmail; + case FIRAuthErrorCodeInvalidCredential: + return kFIRAuthErrorMessageInvalidCredential; + case FIRAuthErrorCodeUserDisabled: + return kFIRAuthErrorMessageUserDisabled; + case FIRAuthErrorCodeEmailAlreadyInUse: + return kFIRAuthErrorMessageEmailAlreadyInUse; + case FIRAuthErrorCodeWrongPassword: + return kFIRAuthErrorMessageWrongPassword; + case FIRAuthErrorCodeTooManyRequests: + return kFIRAuthErrorMessageTooManyRequests; + case FIRAuthErrorCodeAccountExistsWithDifferentCredential: + return kFIRAuthErrorMessageAccountExistsWithDifferentCredential; + case FIRAuthErrorCodeRequiresRecentLogin: + return kFIRAuthErrorMessageRequiresRecentLogin; + case FIRAuthErrorCodeProviderAlreadyLinked: + return kFIRAuthErrorMessageProviderAlreadyLinked; + case FIRAuthErrorCodeNoSuchProvider: + return kFIRAuthErrorMessageNoSuchProvider; + case FIRAuthErrorCodeInvalidUserToken: + return kFIRAuthErrorMessageInvalidUserToken; + case FIRAuthErrorCodeNetworkError: + return kFIRAuthErrorMessageNetworkError; + case FIRAuthErrorCodeKeychainError: + return kFIRAuthErrorMessageKeychainError; + case FIRAuthErrorCodeMissingClientIdentifier: + return kFIRAuthErrorMessageMissingClientIdentifier; + case FIRAuthErrorCodeUserTokenExpired: + return kFIRAuthErrorMessageUserTokenExpired; + case FIRAuthErrorCodeUserNotFound: + return kFIRAuthErrorMessageUserNotFound; + case FIRAuthErrorCodeInvalidAPIKey: + return kFIRAuthErrorMessageInvalidAPIKey; + case FIRAuthErrorCodeCredentialAlreadyInUse: + return kFIRAuthErrorMessageCredentialAlreadyInUse; + case FIRAuthErrorCodeInternalError: + return kFIRAuthErrorMessageInternalError; + case FIRAuthErrorCodeUserMismatch: + return FIRAuthErrorMessageUserMismatch; + case FIRAuthErrorCodeOperationNotAllowed: + return kFIRAuthErrorMessageOperationNotAllowed; + case FIRAuthErrorCodeWeakPassword: + return kFIRAuthErrorMessageWeakPassword; + case FIRAuthErrorCodeAppNotAuthorized: + return kFIRAuthErrorMessageAppNotAuthorized; + case FIRAuthErrorCodeExpiredActionCode: + return kFIRAuthErrorMessageExpiredActionCode; + case FIRAuthErrorCodeInvalidActionCode: + return kFIRAuthErrorMessageInvalidActionCode; + case FIRAuthErrorCodeInvalidSender: + return kFIRAuthErrorMessageInvalidSender; + case FIRAuthErrorCodeInvalidMessagePayload: + return kFIRAuthErrorMessageInvalidMessagePayload; + case FIRAuthErrorCodeInvalidRecipientEmail: + return kFIRAuthErrorMessageInvalidRecipientEmail; + case FIRAuthErrorCodeMissingIosBundleID: + return kFIRAuthErrorMessageMissingIosBundleID; + case FIRAuthErrorCodeMissingAndroidPackageName: + return kFIRAuthErrorMessageMissingAndroidPackageName; + case FIRAuthErrorCodeUnauthorizedDomain: + return kFIRAuthErrorMessageUnauthorizedDomain; + case FIRAuthErrorCodeInvalidContinueURI: + return kFIRAuthErrorMessageInvalidContinueURI; + case FIRAuthErrorCodeMissingContinueURI: + return kFIRAuthErrorMessageMissingContinueURI; + case FIRAuthErrorCodeMissingEmail: + return kFIRAuthErrorMessageMissingEmail; + case FIRAuthErrorCodeMissingPhoneNumber: + return kFIRAuthErrorMessageMissingPhoneNumber; + case FIRAuthErrorCodeInvalidPhoneNumber: + return kFIRAuthErrorMessageInvalidPhoneNumber; + case FIRAuthErrorCodeMissingVerificationCode: + return kFIRAuthErrorMessageMissingVerificationCode; + case FIRAuthErrorCodeInvalidVerificationCode: + return kFIRAuthErrorMessageInvalidVerificationCode; + case FIRAuthErrorCodeMissingVerificationID: + return kFIRAuthErrorMessageMissingVerificationID; + case FIRAuthErrorCodeInvalidVerificationID: + return kFIRAuthErrorMessageInvalidVerificationID; + case FIRAuthErrorCodeSessionExpired: + return kFIRAuthErrorMessageSessionExpired; + case FIRAuthErrorCodeMissingAppCredential: + return kFIRAuthErrorMessageMissingAppCredential; + case FIRAuthErrorCodeInvalidAppCredential: + return kFIRAuthErrorMessageInvalidAppCredential; + case FIRAuthErrorCodeQuotaExceeded: + return kFIRAuthErrorMessageQuotaExceeded; + case FIRAuthErrorCodeMissingAppToken: + return kFIRAuthErrorMessageMissingAppToken; + case FIRAuthErrorCodeNotificationNotForwarded: + return kFIRAuthErrorMessageNotificationNotForwarded; + case FIRAuthErrorCodeAppNotVerified: + return kFIRAuthErrorMessageAppNotVerified; + case FIRAuthErrorCodeCaptchaCheckFailed: + return kFIRAuthErrorMessageCaptchaCheckFailed; + case FIRAuthErrorCodeWebContextAlreadyPresented: + return kFIRAuthErrorMessageWebContextAlreadyPresented; + case FIRAuthErrorCodeWebContextCancelled: + return kFIRAuthErrorMessageWebContextCancelled; + case FIRAuthErrorCodeInvalidClientID: + return kFIRAuthErrorMessageInvalidClientID; + case FIRAuthErrorCodeAppVerificationUserInteractionFailure: + return kFIRAuthErrorMessageAppVerificationUserInteractionFailure; + case FIRAuthErrorCodeWebNetworkRequestFailed: + return kFIRAuthErrorMessageWebRequestFailed; + case FIRAuthErrorCodeNullUser: + return kFIRAuthErrorMessageNullUser; + case FIRAuthErrorCodeInvalidProviderID: + return kFIRAuthErrorMessageInvalidProviderID; + case FIRAuthErrorCodeInvalidDynamicLinkDomain: + return kFIRAuthErrorMessageInvalidDynamicLinkDomain; + case FIRAuthErrorCodeWebInternalError: + return kFIRAuthErrorMessageWebInternalError; + case FIRAuthErrorCodeWebSignInUserInteractionFailure: + return kFIRAuthErrorMessageAppVerificationUserInteractionFailure; + case FIRAuthErrorCodeMalformedJWT: + return kFIRAuthErrorMessageMalformedJWT; + case FIRAuthErrorCodeLocalPlayerNotAuthenticated: + return kFIRAuthErrorMessageLocalPlayerNotAuthenticated; + case FIRAuthErrorCodeGameKitNotLinked: + return kFIRAuthErrorMessageGameKitNotLinked; + case FIRAuthErrorCodeSecondFactorRequired: + return kFIRAuthErrorMessageSecondFactorRequired; + case FIRAuthErrorCodeMissingMultiFactorSession: + return FIRAuthErrorMessageMissingMultiFactorSession; + case FIRAuthErrorCodeMissingMultiFactorInfo: + return FIRAuthErrorMessageMissingMultiFactorInfo; + case FIRAuthErrorCodeInvalidMultiFactorSession: + return FIRAuthErrorMessageInvalidMultiFactorSession; + case FIRAuthErrorCodeMultiFactorInfoNotFound: + return FIRAuthErrorMessageMultiFactorInfoNotFound; + case FIRAuthErrorCodeAdminRestrictedOperation: + return FIRAuthErrorMessageAdminRestrictedOperation; + case FIRAuthErrorCodeUnverifiedEmail: + return FIRAuthErrorMessageUnverifiedEmail; + case FIRAuthErrorCodeSecondFactorAlreadyEnrolled: + return FIRAuthErrorMessageSecondFactorAlreadyEnrolled; + case FIRAuthErrorCodeMaximumSecondFactorCountExceeded: + return FIRAuthErrorMessageMaximumSecondFactorCountExceeded; + case FIRAuthErrorCodeUnsupportedFirstFactor: + return FIRAuthErrorMessageUnsupportedFirstFactor; + case FIRAuthErrorCodeEmailChangeNeedsVerification: + return FIRAuthErrorMessageEmailChangeNeedsVerification; + case FIRAuthErrorCodeDynamicLinkNotActivated: + return kFIRAuthErrorMessageDynamicLinkNotActivated; + case FIRAuthErrorCodeRejectedCredential: + return kFIRAuthErrorMessageRejectedCredential; + case FIRAuthErrorCodeMissingOrInvalidNonce: + return kFIRAuthErrorMessageMissingOrInvalidNonce; + } +} + +/** @var FIRAuthErrorCodeString + @brief The the error short string, based on the error code. + @remarks No default case so that we get a compiler warning if a new value was added to the enum. + */ +static NSString *const FIRAuthErrorCodeString(FIRAuthErrorCode code) { + switch (code) { + case FIRAuthErrorCodeInvalidCustomToken: + return @"ERROR_INVALID_CUSTOM_TOKEN"; + case FIRAuthErrorCodeCustomTokenMismatch: + return @"ERROR_CUSTOM_TOKEN_MISMATCH"; + case FIRAuthErrorCodeInvalidEmail: + return @"ERROR_INVALID_EMAIL"; + case FIRAuthErrorCodeInvalidCredential: + return @"ERROR_INVALID_CREDENTIAL"; + case FIRAuthErrorCodeUserDisabled: + return @"ERROR_USER_DISABLED"; + case FIRAuthErrorCodeEmailAlreadyInUse: + return @"ERROR_EMAIL_ALREADY_IN_USE"; + case FIRAuthErrorCodeWrongPassword: + return @"ERROR_WRONG_PASSWORD"; + case FIRAuthErrorCodeTooManyRequests: + return @"ERROR_TOO_MANY_REQUESTS"; + case FIRAuthErrorCodeAccountExistsWithDifferentCredential: + return @"ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL"; + case FIRAuthErrorCodeRequiresRecentLogin: + return @"ERROR_REQUIRES_RECENT_LOGIN"; + case FIRAuthErrorCodeProviderAlreadyLinked: + return @"ERROR_PROVIDER_ALREADY_LINKED"; + case FIRAuthErrorCodeNoSuchProvider: + return @"ERROR_NO_SUCH_PROVIDER"; + case FIRAuthErrorCodeInvalidUserToken: + return @"ERROR_INVALID_USER_TOKEN"; + case FIRAuthErrorCodeNetworkError: + return @"ERROR_NETWORK_REQUEST_FAILED"; + case FIRAuthErrorCodeKeychainError: + return @"ERROR_KEYCHAIN_ERROR"; + case FIRAuthErrorCodeMissingClientIdentifier: + return @"ERROR_MISSING_CLIENT_IDENTIFIER"; + case FIRAuthErrorCodeUserTokenExpired: + return @"ERROR_USER_TOKEN_EXPIRED"; + case FIRAuthErrorCodeUserNotFound: + return @"ERROR_USER_NOT_FOUND"; + case FIRAuthErrorCodeInvalidAPIKey: + return @"ERROR_INVALID_API_KEY"; + case FIRAuthErrorCodeCredentialAlreadyInUse: + return @"ERROR_CREDENTIAL_ALREADY_IN_USE"; + case FIRAuthErrorCodeInternalError: + return @"ERROR_INTERNAL_ERROR"; + case FIRAuthErrorCodeUserMismatch: + return @"ERROR_USER_MISMATCH"; + case FIRAuthErrorCodeOperationNotAllowed: + return @"ERROR_OPERATION_NOT_ALLOWED"; + case FIRAuthErrorCodeWeakPassword: + return @"ERROR_WEAK_PASSWORD"; + case FIRAuthErrorCodeAppNotAuthorized: + return @"ERROR_APP_NOT_AUTHORIZED"; + case FIRAuthErrorCodeExpiredActionCode: + return @"ERROR_EXPIRED_ACTION_CODE"; + case FIRAuthErrorCodeInvalidActionCode: + return @"ERROR_INVALID_ACTION_CODE"; + case FIRAuthErrorCodeInvalidMessagePayload: + return @"ERROR_INVALID_MESSAGE_PAYLOAD"; + case FIRAuthErrorCodeInvalidSender: + return @"ERROR_INVALID_SENDER"; + case FIRAuthErrorCodeInvalidRecipientEmail: + return @"ERROR_INVALID_RECIPIENT_EMAIL"; + case FIRAuthErrorCodeMissingIosBundleID: + return @"ERROR_MISSING_IOS_BUNDLE_ID"; + case FIRAuthErrorCodeMissingAndroidPackageName: + return @"ERROR_MISSING_ANDROID_PKG_NAME"; + case FIRAuthErrorCodeUnauthorizedDomain: + return @"ERROR_UNAUTHORIZED_DOMAIN"; + case FIRAuthErrorCodeInvalidContinueURI: + return @"ERROR_INVALID_CONTINUE_URI"; + case FIRAuthErrorCodeMissingContinueURI: + return @"ERROR_MISSING_CONTINUE_URI"; + case FIRAuthErrorCodeMissingEmail: + return @"ERROR_MISSING_EMAIL"; + case FIRAuthErrorCodeMissingPhoneNumber: + return @"ERROR_MISSING_PHONE_NUMBER"; + case FIRAuthErrorCodeInvalidPhoneNumber: + return @"ERROR_INVALID_PHONE_NUMBER"; + case FIRAuthErrorCodeMissingVerificationCode: + return @"ERROR_MISSING_VERIFICATION_CODE"; + case FIRAuthErrorCodeInvalidVerificationCode: + return @"ERROR_INVALID_VERIFICATION_CODE"; + case FIRAuthErrorCodeMissingVerificationID: + return @"ERROR_MISSING_VERIFICATION_ID"; + case FIRAuthErrorCodeInvalidVerificationID: + return @"ERROR_INVALID_VERIFICATION_ID"; + case FIRAuthErrorCodeSessionExpired: + return @"ERROR_SESSION_EXPIRED"; + case FIRAuthErrorCodeMissingAppCredential: + return @"MISSING_APP_CREDENTIAL"; + case FIRAuthErrorCodeInvalidAppCredential: + return @"INVALID_APP_CREDENTIAL"; + case FIRAuthErrorCodeQuotaExceeded: + return @"ERROR_QUOTA_EXCEEDED"; + case FIRAuthErrorCodeMissingAppToken: + return @"ERROR_MISSING_APP_TOKEN"; + case FIRAuthErrorCodeNotificationNotForwarded: + return @"ERROR_NOTIFICATION_NOT_FORWARDED"; + case FIRAuthErrorCodeAppNotVerified: + return @"ERROR_APP_NOT_VERIFIED"; + case FIRAuthErrorCodeCaptchaCheckFailed: + return @"ERROR_CAPTCHA_CHECK_FAILED"; + case FIRAuthErrorCodeWebContextAlreadyPresented: + return @"ERROR_WEB_CONTEXT_ALREADY_PRESENTED"; + case FIRAuthErrorCodeWebContextCancelled: + return @"ERROR_WEB_CONTEXT_CANCELLED"; + case FIRAuthErrorCodeInvalidClientID: + return @"ERROR_INVALID_CLIENT_ID"; + case FIRAuthErrorCodeAppVerificationUserInteractionFailure: + return @"ERROR_APP_VERIFICATION_FAILED"; + case FIRAuthErrorCodeWebNetworkRequestFailed: + return @"ERROR_WEB_NETWORK_REQUEST_FAILED"; + case FIRAuthErrorCodeNullUser: + return @"ERROR_NULL_USER"; + case FIRAuthErrorCodeInvalidProviderID: + return @"ERROR_INVALID_PROVIDER_ID"; + case FIRAuthErrorCodeInvalidDynamicLinkDomain: + return @"ERROR_INVALID_DYNAMIC_LINK_DOMAIN"; + case FIRAuthErrorCodeWebInternalError: + return @"ERROR_WEB_INTERNAL_ERROR"; + case FIRAuthErrorCodeWebSignInUserInteractionFailure: + return @"ERROR_WEB_USER_INTERACTION_FAILURE"; + case FIRAuthErrorCodeMalformedJWT: + return @"ERROR_MALFORMED_JWT"; + case FIRAuthErrorCodeLocalPlayerNotAuthenticated: + return @"ERROR_LOCAL_PLAYER_NOT_AUTHENTICATED"; + case FIRAuthErrorCodeGameKitNotLinked: + return @"ERROR_GAME_KIT_NOT_LINKED"; + case FIRAuthErrorCodeSecondFactorRequired: + return @"ERROR_SECOND_FACTOR_REQUIRED"; + case FIRAuthErrorCodeMissingMultiFactorSession: + return @"ERROR_MISSING_MULTI_FACTOR_SESSION"; + case FIRAuthErrorCodeMissingMultiFactorInfo: + return @"ERROR_MISSING_MULTI_FACTOR_INFO"; + case FIRAuthErrorCodeInvalidMultiFactorSession: + return @"ERROR_INVALID_MULTI_FACTOR_SESSION"; + case FIRAuthErrorCodeMultiFactorInfoNotFound: + return @"ERROR_MULTI_FACTOR_INFO_NOT_FOUND"; + case FIRAuthErrorCodeAdminRestrictedOperation: + return @"ERROR_ADMIN_RESTRICTED_OPERATION"; + case FIRAuthErrorCodeUnverifiedEmail: + return @"ERROR_UNVERIFIED_EMAIL"; + case FIRAuthErrorCodeSecondFactorAlreadyEnrolled: + return @"ERROR_SECOND_FACTOR_ALREADY_ENROLLED"; + case FIRAuthErrorCodeMaximumSecondFactorCountExceeded: + return @"ERROR_MAXIMUM_SECOND_FACTOR_COUNT_EXCEEDED"; + case FIRAuthErrorCodeUnsupportedFirstFactor: + return @"ERROR_UNSUPPORTED_FIRST_FACTOR"; + case FIRAuthErrorCodeEmailChangeNeedsVerification: + return @"ERROR_EMAIL_CHANGE_NEEDS_VERIFICATION"; + case FIRAuthErrorCodeDynamicLinkNotActivated: + return @"ERROR_DYNAMIC_LINK_NOT_ACTIVATED"; + case FIRAuthErrorCodeRejectedCredential: + return @"ERROR_REJECTED_CREDENTIAL"; + case FIRAuthErrorCodeMissingOrInvalidNonce: + return @"ERROR_MISSING_OR_INVALID_NONCE"; + } +} + +@implementation FIRAuthErrorUtils + ++ (NSError *)errorWithCode:(FIRAuthInternalErrorCode)code { + return [self errorWithCode:code message:nil]; +} + ++ (NSError *)errorWithCode:(FIRAuthInternalErrorCode)code message:(nullable NSString *)message { + NSDictionary *userInfo = nil; + if (message.length) { + userInfo = @{NSLocalizedDescriptionKey : message}; + } + return [self errorWithCode:code userInfo:userInfo]; +} + ++ (NSError *)errorWithCode:(FIRAuthInternalErrorCode)code + underlyingError:(nullable NSError *)underlyingError { + NSDictionary *errorUserInfo; + if (underlyingError) { + errorUserInfo = @{NSUnderlyingErrorKey : underlyingError}; + } + return [self errorWithCode:code userInfo:errorUserInfo]; +} + ++ (NSError *)errorWithCode:(FIRAuthInternalErrorCode)code + userInfo:(nullable NSDictionary *)userInfo { + BOOL isPublic = (code & FIRAuthPublicErrorCodeFlag) == FIRAuthPublicErrorCodeFlag; + if (isPublic) { + // This is a public error. Return it as a public error and add a description. + NSInteger errorCode = code & ~FIRAuthPublicErrorCodeFlag; + NSMutableDictionary *errorUserInfo = [NSMutableDictionary dictionary]; + if (userInfo) { + [errorUserInfo addEntriesFromDictionary:userInfo]; + } + if (!errorUserInfo[NSLocalizedDescriptionKey]) { + errorUserInfo[NSLocalizedDescriptionKey] = FIRAuthErrorDescription(errorCode); + } + errorUserInfo[FIRAuthErrorUserInfoNameKey] = FIRAuthErrorCodeString(errorCode); + return [NSError errorWithDomain:FIRAuthErrorDomain code:errorCode userInfo:errorUserInfo]; + } else { + // This is an internal error. Wrap it in an internal error. + NSError *error = [NSError errorWithDomain:FIRAuthInternalErrorDomain + code:code + userInfo:userInfo]; + return [self errorWithCode:FIRAuthInternalErrorCodeInternalError underlyingError:error]; + } +} + ++ (NSError *)RPCRequestEncodingErrorWithUnderlyingError:(NSError *)underlyingError { + return [self errorWithCode:FIRAuthInternalErrorCodeRPCRequestEncodingError + underlyingError:underlyingError]; +} + ++ (NSError *)JSONSerializationErrorForUnencodableType { + return [self errorWithCode:FIRAuthInternalErrorCodeJSONSerializationError]; +} + ++ (NSError *)JSONSerializationErrorWithUnderlyingError:(NSError *)underlyingError { + return [self errorWithCode:FIRAuthInternalErrorCodeJSONSerializationError + underlyingError:underlyingError]; +} + ++ (NSError *)networkErrorWithUnderlyingError:(NSError *)underlyingError { + return [self errorWithCode:FIRAuthInternalErrorCodeNetworkError underlyingError:underlyingError]; +} + ++ (NSError *)unexpectedErrorResponseWithData:(NSData *)data + underlyingError:(NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (data) { + userInfo[FIRAuthErrorUserInfoDataKey] = data; + } + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + return [self errorWithCode:FIRAuthInternalErrorCodeUnexpectedErrorResponse + userInfo:[userInfo copy]]; +} + ++ (NSError *)unexpectedErrorResponseWithDeserializedResponse:(id)deserializedResponse { + NSDictionary *userInfo; + if (deserializedResponse) { + userInfo = @{ + FIRAuthErrorUserInfoDeserializedResponseKey : deserializedResponse, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeUnexpectedErrorResponse userInfo:userInfo]; +} + ++ (NSError *)malformedJWTErrorWithToken:(NSString *)token + underlyingError:(NSError *_Nullable)underlyingError { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:kFIRAuthErrorMessageMalformedJWT + forKey:NSLocalizedDescriptionKey]; + [userInfo setObject:token forKey:FIRAuthErrorUserInfoDataKey]; + if (underlyingError != nil) { + [userInfo setObject:underlyingError forKey:NSUnderlyingErrorKey]; + } + return [self errorWithCode:FIRAuthInternalErrorCodeMalformedJWT userInfo:[userInfo copy]]; +} + ++ (NSError *)unexpectedResponseWithData:(NSData *)data underlyingError:(NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (data) { + userInfo[FIRAuthErrorUserInfoDataKey] = data; + } + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + return [self errorWithCode:FIRAuthInternalErrorCodeUnexpectedResponse userInfo:[userInfo copy]]; +} + ++ (NSError *)unexpectedResponseWithDeserializedResponse:(id)deserializedResponse { + NSDictionary *userInfo; + if (deserializedResponse) { + userInfo = @{ + FIRAuthErrorUserInfoDeserializedResponseKey : deserializedResponse, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeUnexpectedResponse userInfo:userInfo]; +} + ++ (NSError *)unexpectedResponseWithDeserializedResponse:(nullable id)deserializedResponse + underlyingError:(NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (deserializedResponse) { + userInfo[FIRAuthErrorUserInfoDeserializedResponseKey] = deserializedResponse; + } + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + return [self errorWithCode:FIRAuthInternalErrorCodeUnexpectedResponse userInfo:[userInfo copy]]; +} + ++ (NSError *)RPCResponseDecodingErrorWithDeserializedResponse:(id)deserializedResponse + underlyingError:(NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (deserializedResponse) { + userInfo[FIRAuthErrorUserInfoDeserializedResponseKey] = deserializedResponse; + } + if (underlyingError) { + userInfo[NSUnderlyingErrorKey] = underlyingError; + } + return [self errorWithCode:FIRAuthInternalErrorCodeRPCResponseDecodingError + userInfo:[userInfo copy]]; +} + ++ (NSError *)emailAlreadyInUseErrorWithEmail:(nullable NSString *)email { + NSDictionary *userInfo; + if (email.length) { + userInfo = @{ + FIRAuthErrorUserInfoEmailKey : email, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeEmailAlreadyInUse userInfo:userInfo]; +} + ++ (NSError *)userDisabledErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeUserDisabled message:message]; +} + ++ (NSError *)wrongPasswordErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeWrongPassword message:message]; +} + ++ (NSError *)tooManyRequestsErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeTooManyRequests message:message]; +} + ++ (NSError *)invalidCustomTokenErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidCustomToken message:message]; +} + ++ (NSError *)customTokenMistmatchErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeCustomTokenMismatch message:message]; +} + ++ (NSError *)invalidCredentialErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidCredential message:message]; +} + ++ (NSError *)requiresRecentLoginErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeRequiresRecentLogin message:message]; +} + ++ (NSError *)invalidUserTokenErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidUserToken message:message]; +} + ++ (NSError *)invalidEmailErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidEmail message:message]; +} + ++ (NSError *)accountExistsWithDifferentCredentialErrorWithEmail:(nullable NSString *)email + updatedCredential: + (nullable FIRAuthCredential *)updatedCredential { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (email) { + userInfo[FIRAuthErrorUserInfoEmailKey] = email; + } + if (updatedCredential) { + userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey] = updatedCredential; + } + return [self errorWithCode:FIRAuthInternalErrorCodeAccountExistsWithDifferentCredential + userInfo:userInfo]; +} + ++ (NSError *)providerAlreadyLinkedError { + return [self errorWithCode:FIRAuthInternalErrorCodeProviderAlreadyLinked]; +} + ++ (NSError *)noSuchProviderError { + return [self errorWithCode:FIRAuthInternalErrorCodeNoSuchProvider]; +} + ++ (NSError *)userTokenExpiredErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeUserTokenExpired message:message]; +} + ++ (NSError *)userNotFoundErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeUserNotFound message:message]; +} + ++ (NSError *)invalidAPIKeyError { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidAPIKey]; +} + ++ (NSError *)userMismatchError { + return [self errorWithCode:FIRAuthInternalErrorCodeUserMismatch]; +} + ++ (NSError *)credentialAlreadyInUseErrorWithMessage:(nullable NSString *)message + credential:(nullable FIRAuthCredential *)credential + email:(nullable NSString *)email { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (credential) { + userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey] = credential; + } + if (email.length) { + userInfo[FIRAuthErrorUserInfoEmailKey] = email; + } + if (userInfo.count) { + return [self errorWithCode:FIRAuthInternalErrorCodeCredentialAlreadyInUse userInfo:userInfo]; + } + return [self errorWithCode:FIRAuthInternalErrorCodeCredentialAlreadyInUse message:message]; +} + ++ (NSError *)operationNotAllowedErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeOperationNotAllowed message:message]; +} + ++ (NSError *)weakPasswordErrorWithServerResponseReason:(nullable NSString *)reason { + NSDictionary *userInfo; + if (reason.length) { + userInfo = @{ + NSLocalizedFailureReasonErrorKey : reason, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeWeakPassword userInfo:userInfo]; +} + ++ (NSError *)appNotAuthorizedError { + return [self errorWithCode:FIRAuthInternalErrorCodeAppNotAuthorized]; +} + ++ (NSError *)expiredActionCodeErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeExpiredActionCode message:message]; +} + ++ (NSError *)invalidActionCodeErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidActionCode message:message]; +} + ++ (NSError *)invalidMessagePayloadErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidMessagePayload message:message]; +} + ++ (NSError *)invalidSenderErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidSender message:message]; +} + ++ (NSError *)invalidRecipientEmailErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidRecipientEmail message:message]; +} + ++ (NSError *)missingIosBundleIDErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthinternalErrorCodeMissingIosBundleID message:message]; +} + ++ (NSError *)missingAndroidPackageNameErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingAndroidPackageName message:message]; +} + ++ (NSError *)unauthorizedDomainErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeUnauthorizedDomain message:message]; +} + ++ (NSError *)invalidContinueURIErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidContinueURI message:message]; +} + ++ (NSError *)missingContinueURIErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingContinueURI message:message]; +} + ++ (NSError *)missingEmailErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingEmail message:message]; +} + ++ (NSError *)missingPhoneNumberErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingPhoneNumber message:message]; +} + ++ (NSError *)invalidPhoneNumberErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidPhoneNumber message:message]; +} + ++ (NSError *)missingVerificationCodeErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingVerificationCode message:message]; +} + ++ (NSError *)invalidVerificationCodeErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidVerificationCode message:message]; +} + ++ (NSError *)missingVerificationIDErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingVerificationID message:message]; +} + ++ (NSError *)invalidVerificationIDErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidVerificationID message:message]; +} + ++ (NSError *)sessionExpiredErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeSessionExpired message:message]; +} + ++ (NSError *)missingAppCredentialWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingAppCredential message:message]; +} + ++ (NSError *)invalidAppCredentialWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidAppCredential message:message]; +} + ++ (NSError *)quotaExceededErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeQuotaExceeded message:message]; +} + ++ (NSError *)missingAppTokenErrorWithUnderlyingError:(nullable NSError *)underlyingError { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingAppToken + underlyingError:underlyingError]; +} + ++ (NSError *)localPlayerNotAuthenticatedError { + return [self errorWithCode:FIRAuthInternalErrorCodeLocalPlayerNotAuthenticated]; +} + ++ (NSError *)gameKitNotLinkedError { + return [self errorWithCode:FIRAuthInternalErrorCodeGameKitNotLinked]; +} + +#if TARGET_OS_IOS ++ (NSError *)secondFactorRequiredErrorWithPendingCredential:(NSString *)MFAPendingCredential + hints:(NSArray *)hints { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (MFAPendingCredential && hints) { + FIRMultiFactorResolver *resolver = + [[FIRMultiFactorResolver alloc] initWithMFAPendingCredential:MFAPendingCredential + hints:hints]; + userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey] = resolver; + } + return [self errorWithCode:FIRAuthInternalErrorCodeSecondFactorRequired userInfo:userInfo]; +} +#endif + ++ (NSError *)notificationNotForwardedError { + return [self errorWithCode:FIRAuthInternalErrorCodeNotificationNotForwarded]; +} + ++ (NSError *)appNotVerifiedErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeAppNotVerified message:message]; +} + ++ (NSError *)missingClientIdentifierErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingClientIdentifier message:message]; +} + ++ (NSError *)captchaCheckFailedErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeCaptchaCheckFailed message:message]; +} + ++ (NSError *)webContextAlreadyPresentedErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeWebContextAlreadyPresented message:message]; +} + ++ (NSError *)webContextCancelledErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeWebContextCancelled message:message]; +} + ++ (NSError *)appVerificationUserInteractionFailureWithReason:(NSString *)reason { + NSDictionary *userInfo; + if (reason.length) { + userInfo = @{ + NSLocalizedFailureReasonErrorKey : reason, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeAppVerificationUserInteractionFailure + userInfo:userInfo]; +} + ++ (NSError *)webSignInUserInteractionFailureWithReason:(nullable NSString *)reason { + NSDictionary *userInfo; + if (reason.length) { + userInfo = @{ + NSLocalizedFailureReasonErrorKey : reason, + }; + } + return [self errorWithCode:FIRAuthInternalErrorCodeWebSignInUserInteractionFailure + userInfo:userInfo]; +} + ++ (nullable NSError *)URLResponseErrorWithCode:(NSString *)code + message:(nullable NSString *)message { + if ([code isEqualToString:kURLResponseErrorCodeInvalidClientID]) { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidClientID message:message]; + } + if ([code isEqualToString:kURLResponseErrorCodeNetworkRequestFailed]) { + return [self errorWithCode:FIRAuthInternalErrorCodeWebNetworkRequestFailed message:message]; + } + if ([code isEqualToString:kURLResponseErrorCodeInternalError]) { + return [self errorWithCode:FIRAuthInternalErrorCodeWebInternalError message:message]; + } + return nil; +} + ++ (NSError *)nullUserErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeNullUser message:message]; +} + ++ (NSError *)invalidProviderIDErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidProviderID message:message]; +} + ++ (NSError *)invalidDynamicLinkDomainErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeInvalidDynamicLinkDomain message:message]; +} + ++ (NSError *)missingOrInvalidNonceErrorWithMessage:(nullable NSString *)message { + return [self errorWithCode:FIRAuthInternalErrorCodeMissingOrInvalidNonce message:message]; +} + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status { + NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status]; + return [self errorWithCode:FIRAuthInternalErrorCodeKeychainError + userInfo:@{ + NSLocalizedFailureReasonErrorKey : failureReason, + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h new file mode 100644 index 00000000..3ae9159d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthExceptionUtils + @brief Utility class used to raise standardized Auth related exceptions. +*/ +@interface FIRAuthExceptionUtils : NSObject + +/** @fn raiseInvalidParameterExceptionWithReason: + @brief raises the "invalid parameter" exception + @param reason string will contain a description of the error. + */ ++ (void)raiseInvalidParameterExceptionWithReason:(nullable NSString *)reason; + +/** @fn raiseMethodNotImplementedExceptionWithReason: + @brief raises the "method not implemented" exception + @param reason string will contain a description of the error. + @see FIRMethodNotImplementedException + */ ++ (void)raiseMethodNotImplementedExceptionWithReason:(nullable NSString *)reason; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.m new file mode 100644 index 00000000..783d4a41 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var FIRMethodNotImplementedException + @brief The name of the "Method Not Implemented" exception. + */ +static NSString *const FIRMethodNotImplementedException = @"FIRMethodNotImplementedException"; + +@implementation FIRAuthExceptionUtils + ++ (void)raiseInvalidParameterExceptionWithReason:(nullable NSString *)reason { + [NSException raise:NSInvalidArgumentException format:@"%@", reason]; +} + ++ (void)raiseMethodNotImplementedExceptionWithReason:(nullable NSString *)reason { + NSException *exception = [NSException exceptionWithName:FIRMethodNotImplementedException + reason:reason + userInfo:nil]; + [exception raise]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h new file mode 100644 index 00000000..75415c61 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h @@ -0,0 +1,530 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @var FIRAuthPublicErrorCodeFlag + @brief Bitmask value indicating the error represents a public error code when this bit is + zeroed. Error codes which don't contain this flag will be wrapped in an @c NSError whose + code is @c FIRAuthErrorCodeInternalError. + */ +static const NSInteger FIRAuthPublicErrorCodeFlag = 1 << 20; + +/** @var FIRAuthInternalErrorDomain + @brief The Firebase Auth error domain for internal errors. + */ +extern NSString *const FIRAuthInternalErrorDomain; + +/** @var FIRAuthErrorUserInfoDeserializedResponseKey + @brief Errors with the code @c FIRAuthErrorCodeUnexpectedResponseError, + @c FIRAuthErrorCodeUnexpectedErrorResponseError, and + @c FIRAuthInternalErrorCodeRPCResponseDecodingError may contain an @c NSError.userInfo + dictionary which contains this key. The value associated with this key is an object of + unspecified contents containing the deserialized server response. + */ +extern NSString *const FIRAuthErrorUserInfoDeserializedResponseKey; + +/** @var FIRAuthErrorUserInfoDataKey + @brief Errors with the code @c FIRAuthErrorCodeUnexpectedResponseError or + @c FIRAuthErrorCodeUnexpectedErrorResponseError may contain an @c NSError.userInfo + dictionary which contains this key. The value associated with this key is an @c NSString + which represents the response from a server to an RPC which could not be deserialized. + */ +extern NSString *const FIRAuthErrorUserInfoDataKey; + +/** @var FIRAuthInternalErrorCode + @brief Error codes used internally by Firebase Auth. + @remarks All errors are generated using an internal error code. These errors are automatically + converted to the appropriate public version of the @c NSError by the methods in + @c FIRAuthErrorUtils + */ +typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) { + /** @var FIRAuthInternalErrorCodeNetworkError + @brief Indicates a network error occurred (such as a timeout, interrupted connection, or + unreachable host.) + @remarks These types of errors are often recoverable with a retry. + + See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details about + the network error which occurred. + */ + FIRAuthInternalErrorCodeNetworkError = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNetworkError, + + /** @var FIRAuthInternalErrorCodeEmailAlreadyInUse + @brief The email used to attempt a sign-up already exists. + */ + FIRAuthInternalErrorCodeEmailAlreadyInUse = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeEmailAlreadyInUse, + + /** @var FIRAuthInternalErrorCodeUserDisabled + @brief Indicates the user's account is disabled on the server side. + */ + FIRAuthInternalErrorCodeUserDisabled = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserDisabled, + + /** @var FIRAuthInternalErrorCodeWrongPassword + @brief Indicates the user attempted sign in with a wrong password + */ + FIRAuthInternalErrorCodeWrongPassword = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeWrongPassword, + + /** @var FIRAuthInternalErrorCodeKeychainError + @brief Indicates an error occurred accessing the keychain. + @remarks The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo dictionary + will contain more information about the error encountered. + */ + FIRAuthInternalErrorCodeKeychainError = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeKeychainError, + + /** @var FIRAuthInternalErrorCodeMissingClientIdentifier + @brief Indicates an error for when the client identifier is missing. + */ + FIRAuthInternalErrorCodeMissingClientIdentifier = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingClientIdentifier, + + /** @var FIRAuthInternalErrorCodeInternalError + @brief An internal error occurred. + @remarks This value is here for consistency. It's also used to make the implementation of + wrapping internal errors simpler. + */ + FIRAuthInternalErrorCodeInternalError = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInternalError, + + /** @var FIRAuthInternalErrorCodeTooManyRequests + @brief Indicates that too many requests were made to a server method. + */ + FIRAuthInternalErrorCodeTooManyRequests = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeTooManyRequests, + + /** @var FIRAuthInternalErrorCodeInvalidCustomToken + @brief Indicates a validation error with the custom token. + */ + FIRAuthInternalErrorCodeInvalidCustomToken = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidCustomToken, + + /** @var FIRAuthInternalErrorCodeCredentialMismatch + @brief Indicates the service account and the API key belong to different projects. + */ + FIRAuthInternalErrorCodeCustomTokenMismatch = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeCustomTokenMismatch, + + /** @var FIRAuthInternalErrorCodeInvalidCredential + @brief Indicates the IDP token or requestUri is invalid. + */ + FIRAuthInternalErrorCodeInvalidCredential = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidCredential, + + /** @var FIRAuthInternalErrorCodeRequiresRecentLogin + @brief Indicates the user has attemped to change email or password more than 5 minutes after + signing in. + */ + FIRAuthInternalErrorCodeRequiresRecentLogin = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeRequiresRecentLogin, + + /** @var FIRAuthInternalErrorCodeInvalidUserToken + @brief Indicates user's saved auth credential is invalid, the user needs to sign in again. + */ + FIRAuthInternalErrorCodeInvalidUserToken = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidUserToken, + + /** @var FIRAuthInternalErrorCodeInvalidEmail + @brief Indicates the email identifier is invalid. + */ + FIRAuthInternalErrorCodeInvalidEmail = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidEmail, + + /** @var FIRAuthInternalErrorCodeAccountExistsWithDifferentCredential + @brief Indicates account linking is needed. + */ + FIRAuthInternalErrorCodeAccountExistsWithDifferentCredential = + FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAccountExistsWithDifferentCredential, + + /** @var FIRAuthInternalErrorCodeProviderAlreadyLinked + @brief Indicates an attempt to link a provider to which we are already linked. + */ + FIRAuthInternalErrorCodeProviderAlreadyLinked = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeProviderAlreadyLinked, + + /** @var FIRAuthInternalErrorCodeNoSuchProvider + @brief Indicates an attempt to unlink a provider that is not is not linked. + */ + FIRAuthInternalErrorCodeNoSuchProvider = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeNoSuchProvider, + + /** @var FIRAuthInternalErrorCodeUserTokenExpired + @brief Indicates the token issue time is older than account's valid_since time. + */ + FIRAuthInternalErrorCodeUserTokenExpired = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeUserTokenExpired, + + /** @var FIRAuthInternalErrorCodeUserNotFound + @brief Indicates the user account was been found. + */ + FIRAuthInternalErrorCodeUserNotFound = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserNotFound, + + /** @var FIRAuthInternalErrorCodeInvalidAPIKey + @brief Indicates an invalid API Key was supplied in the request. + */ + FIRAuthInternalErrorCodeInvalidAPIKey = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidAPIKey, + + /** @var FIRAuthInternalErrorCodeOperationNotAllowed + @brief Indicates that admin disabled sign-in with the specified IDP. + */ + FIRAuthInternalErrorCodeOperationNotAllowed = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeOperationNotAllowed, + + /** @var FIRAuthInternalErrorCodeUserMismatch + @brief Indicates that user attempted to reauthenticate with a user other than the current + user. + */ + FIRAuthInternalErrorCodeUserMismatch = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserMismatch, + + /** @var FIRAuthInternalErrorCodeCredentialAlreadyInUse + @brief Indicates an attempt to link with a credential that has already been linked with a + different Firebase account. + */ + FIRAuthInternalErrorCodeCredentialAlreadyInUse = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeCredentialAlreadyInUse, + + /** @var FIRAuthInternalErrorCodeWeakPassword + @brief Indicates an attempt to set a password that is considered too weak. + */ + FIRAuthInternalErrorCodeWeakPassword = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWeakPassword, + + /** @var FIRAuthInternalErrorCodeAppNotAuthorized + @brief Indicates the App is not authorized to use Firebase Authentication with the + provided API Key. + */ + FIRAuthInternalErrorCodeAppNotAuthorized = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeAppNotAuthorized, + + /** @var FIRAuthInternalErrorCodeExpiredActionCode + @brief Indicates the OOB code is expired. + */ + FIRAuthInternalErrorCodeExpiredActionCode = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeExpiredActionCode, + + /** @var FIRAuthInternalErrorCodeInvalidActionCode + @brief Indicates the OOB code is invalid. + */ + FIRAuthInternalErrorCodeInvalidActionCode = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidActionCode, + + /** Indicates that there are invalid parameters in the payload during a "send password reset email + * " attempt. + */ + FIRAuthInternalErrorCodeInvalidMessagePayload = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidMessagePayload, + + /** Indicates that the sender email is invalid during a "send password reset email" attempt. + */ + FIRAuthInternalErrorCodeInvalidSender = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidSender, + + /** Indicates that the recipient email is invalid. + */ + FIRAuthInternalErrorCodeInvalidRecipientEmail = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidRecipientEmail, + + /** Indicates that the iOS bundle ID is missing when a iOS App Store ID is provided. + */ + FIRAuthinternalErrorCodeMissingIosBundleID = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingIosBundleID, + + /** Indicates that the android package name is missing when the @c androidInstallApp flag is set + to true. + */ + FIRAuthInternalErrorCodeMissingAndroidPackageName = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingAndroidPackageName, + + /** Indicates that the domain specified in the continue URL is not whitelisted in the Firebase + console. + */ + FIRAuthInternalErrorCodeUnauthorizedDomain = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeUnauthorizedDomain, + + /** Indicates that the domain specified in the continue URI is not valid. + */ + FIRAuthInternalErrorCodeInvalidContinueURI = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidContinueURI, + + /** Indicates that a continue URI was not provided in a request to the backend which requires + one. + */ + FIRAuthInternalErrorCodeMissingContinueURI = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingContinueURI, + + /** Indicates that an email address was expected but one was not provided. + */ + FIRAuthInternalErrorCodeMissingEmail = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingEmail, + + /** Indicates that a phone number was not provided in a call to @c verifyPhoneNumber:completion:. + */ + FIRAuthInternalErrorCodeMissingPhoneNumber = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingPhoneNumber, + + /** Indicates that an invalid phone number was provided in a call to @c + verifyPhoneNumber:completion:. + */ + FIRAuthInternalErrorCodeInvalidPhoneNumber = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidPhoneNumber, + + /** Indicates that the phone auth credential was created with an empty verification code. + */ + FIRAuthInternalErrorCodeMissingVerificationCode = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingVerificationCode, + + /** Indicates that an invalid verification code was used in the verifyPhoneNumber request. + */ + FIRAuthInternalErrorCodeInvalidVerificationCode = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidVerificationCode, + + /** Indicates that the phone auth credential was created with an empty verification ID. + */ + FIRAuthInternalErrorCodeMissingVerificationID = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingVerificationID, + + /** Indicates that the APNS device token is missing in the verifyClient request. + */ + FIRAuthInternalErrorCodeMissingAppCredential = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingAppCredential, + + /** Indicates that an invalid APNS device token was used in the verifyClient request. + */ + FIRAuthInternalErrorCodeInvalidAppCredential = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidAppCredential, + + /** Indicates that the reCAPTCHA token is not valid. + */ + FIRAuthInternalErrorCodeCaptchaCheckFailed = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeCaptchaCheckFailed, + + /** Indicates that an invalid verification ID was used in the verifyPhoneNumber request. + */ + FIRAuthInternalErrorCodeInvalidVerificationID = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidVerificationID, + + /** Indicates that the quota of SMS messages for a given project has been exceeded. + */ + FIRAuthInternalErrorCodeQuotaExceeded = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeQuotaExceeded, + + /** Indicates that an attempt was made to present a new web context while one was already being + presented. + */ + FIRAuthInternalErrorCodeWebContextAlreadyPresented = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeWebContextAlreadyPresented, + + /** Indicates that the URL presentation was cancelled prematurely by the user. + */ + FIRAuthInternalErrorCodeWebContextCancelled = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeWebContextCancelled, + + /** Indicates a general failure during the app verification flow. + */ + FIRAuthInternalErrorCodeAppVerificationUserInteractionFailure = + FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAppVerificationUserInteractionFailure, + + /** Indicates that the clientID used to invoke a web flow is invalid. + */ + FIRAuthInternalErrorCodeInvalidClientID = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidClientID, + + /** Indicates that a network request within a SFSafariViewController or WKWebView failed. + */ + FIRAuthInternalErrorCodeWebNetworkRequestFailed = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeWebNetworkRequestFailed, + + /** Indicates that an internal error occurred within a SFSafariViewController or WKWebView. + */ + FIRAuthInternalErrorCodeWebInternalError = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeWebInternalError, + + /** Indicates that an internal error occurred within a SFSafariViewController or WKWebView. + */ + FIRAuthInternalErrorCodeWebSignInUserInteractionFailure = + FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWebSignInUserInteractionFailure, + + // The enum values between 17046 and 17051 are reserved and should NOT be used for new error + // codes. + + /** Indicates that the SMS code has expired + */ + FIRAuthInternalErrorCodeSessionExpired = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeSessionExpired, + + FIRAuthInternalErrorCodeMissingAppToken = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingAppToken, + + FIRAuthInternalErrorCodeNotificationNotForwarded = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeNotificationNotForwarded, + + FIRAuthInternalErrorCodeAppNotVerified = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeAppNotVerified, + + /** Indicates that the Game Center local player was not authenticated. + */ + FIRAuthInternalErrorCodeLocalPlayerNotAuthenticated = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeLocalPlayerNotAuthenticated, + + /** Indicates that the Game Center local player was not authenticated. + */ + FIRAuthInternalErrorCodeGameKitNotLinked = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeGameKitNotLinked, + + /** Indicates that the second factor is required for sign in. + */ + FIRAuthInternalErrorCodeSecondFactorRequired = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeSecondFactorRequired, + + /** Indicates that the multi factor session is missing. + */ + FIRAuthInternalErrorCodeMissingMultiFactorSession = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingMultiFactorSession, + + /** Indicates that the multi factor info is missing. + */ + FIRAuthInternalErrorCodeMissingMultiFactorInfo = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingMultiFactorInfo, + + /** Indicates that the multi factor session is invalid. + */ + FIRAuthInternalErrorCodeInvalidMultiFactorSession = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidMultiFactorSession, + + /** Indicates that the multi factor info is not found. + */ + FIRAuthInternalErrorCodeMultiFactorInfoNotFound = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMultiFactorInfoNotFound, + + /** Indicates that the operation is admin only. + */ + FIRAuthInternalErrorCodeAdminRestrictedOperation = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeAdminRestrictedOperation, + + /** Indicates that the email is unverified. + */ + FIRAuthInternalErrorCodeUnverifiedEmail = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeUnverifiedEmail, + + /** Indicates that the second factor is already enrolled. + */ + FIRAuthInternalErrorCodeSecondFactorAlreadyEnrolled = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeSecondFactorAlreadyEnrolled, + + /** Indicates that the number of multi factors reached the limit. + */ + FIRAuthInternalErrorCodeMaximumSecondFactorCountExceeded = + FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMaximumSecondFactorCountExceeded, + + /** Indicates that the first factor is not supportted. + */ + FIRAuthInternalErrorCodeUnsupportedFirstFactor = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeUnsupportedFirstFactor, + + /** Indicates that the email needs to be verified before changed. + */ + FIRAuthInternalErrorCodeEmailChangeNeedsVerification = + FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeEmailChangeNeedsVerification, + + /** Indicates that the nonce is missing or invalid. + */ + FIRAuthInternalErrorCodeMissingOrInvalidNonce = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeMissingOrInvalidNonce, + + /** Indicates that a non-null user was expected as an argmument to the operation but a null + user was provided. + */ + FIRAuthInternalErrorCodeNullUser = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNullUser, + + /** Indicates that the provider id given for the web operation is invalid. + */ + FIRAuthInternalErrorCodeInvalidProviderID = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidProviderID, + + /** Indicates that the Firebase Dynamic Link domain used is either not configured or is + unauthorized for the current project. + */ + FIRAuthInternalErrorCodeInvalidDynamicLinkDomain = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeInvalidDynamicLinkDomain, + + FIRAuthInternalErrorCodeMalformedJWT = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMalformedJWT, + + /** @var FIRAuthInternalErrorCodeRPCRequestEncodingError + @brief Indicates an error encoding the RPC request. + @remarks This is typically due to some sort of unexpected input value. + + See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details. + */ + FIRAuthInternalErrorCodeRPCRequestEncodingError = 1, + + /** @var FIRAuthInternalErrorCodeJSONSerializationError + @brief Indicates an error serializing an RPC request. + @remarks This is typically due to some sort of unexpected input value. + + If an @c NSJSONSerialization.isValidJSONObject: check fails, the error will contain no + @c NSUnderlyingError key in the @c NSError.userInfo dictionary. If an error was + encountered calling @c NSJSONSerialization.dataWithJSONObject:options:error:, the + resulting error will be associated with the @c NSUnderlyingError key in the + @c NSError.userInfo dictionary. + */ + FIRAuthInternalErrorCodeJSONSerializationError = 2, + + /** @var FIRAuthInternalErrorCodeUnexpectedErrorResponse + @brief Indicates an HTTP error occurred and the data returned either couldn't be deserialized + or couldn't be decoded. + @remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details + about the HTTP error which occurred. + + If the response could be deserialized as JSON then the @c NSError.userInfo dictionary will + contain a value for the key @c FIRAuthErrorUserInfoDeserializedResponseKey which is the + deserialized response value. + + If the response could not be deserialized as JSON then the @c NSError.userInfo dictionary + will contain values for the @c NSUnderlyingErrorKey and @c FIRAuthErrorUserInfoDataKey + keys. + */ + FIRAuthInternalErrorCodeUnexpectedErrorResponse = 3, + + /** @var FIRAuthInternalErrorCodeUnexpectedResponse + @brief Indicates the HTTP response indicated the request was a successes, but the response + contains something other than a JSON-encoded dictionary, or the data type of the response + indicated it is different from the type of response we expected. + @remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary. + If this key is present in the dictionary, it may contain an error from + @c NSJSONSerialization error (indicating the response received was of the wrong data + type). + + See the @c FIRAuthErrorUserInfoDeserializedResponseKey value in the @c NSError.userInfo + dictionary. If the response could be deserialized, it's deserialized representation will + be associated with this key. If the @c NSUnderlyingError value in the @c NSError.userInfo + dictionary is @c nil, this indicates the JSON didn't represent a dictionary. + */ + FIRAuthInternalErrorCodeUnexpectedResponse = 4, + + /** @var FIRAuthInternalErrorCodeRPCResponseDecodingError + @brief Indicates an error decoding the RPC response. + This is typically due to some sort of unexpected response value from the server. + @remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details. + + See the @c FIRErrorUserInfoDecodedResponseKey value in the @c NSError.userInfo dictionary. + The deserialized representation of the response will be associated with this key. + */ + FIRAuthInternalErrorCodeRPCResponseDecodingError = 5, +}; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h new file mode 100644 index 00000000..f7b6b21c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol FIRAuthUIDelegate; + +/** @typedef FIRAuthURLPresentationCompletion + @brief The type of block invoked when the URLPresentation completes. + @param callbackURL The callback URL if the presentation ends with a matching callback. + @param error The error if the presentation fails to start or ends with an error. + */ +typedef void (^FIRAuthURLPresentationCompletion)(NSURL *_Nullable callbackURL, + NSError *_Nullable error); + +/** @typedef FIRAuthCallbackMatcher + @brief The type of block invoked for checking whether a callback URL matches. + @param callbackURL The callback URL to check for match. + @return Whether or not the specific callback URL matches or not. + */ +typedef BOOL (^FIRAuthURLCallbackMatcher)(NSURL *_Nullable callbackURL); + +/** @class FIRAuthURLPresenter + @brief A Class responsible for presenting URL via SFSafariViewController or WKWebView. + */ +@interface FIRAuthURLPresenter : NSObject + +/** @fn presentURL:UIDelegate:callbackMatcher:completion: + @brief Presents an URL to interact with user. + @param URL The URL to present. + @param UIDelegate The UI delegate to present view controller. + @param completion A block to be called either synchronously if the presentation fails to start, + or asynchronously in future on an unspecified thread once the presentation finishes. + */ +- (void)presentURL:(NSURL *)URL + UIDelegate:(nullable id)UIDelegate + callbackMatcher:(FIRAuthURLCallbackMatcher)callbackMatcher + completion:(FIRAuthURLPresentationCompletion)completion; + +/** @fn canHandleURL: + @brief Determines if a URL was produced by the currently presented URL. + @param URL The URL to handle. + @return Whether the URL could be handled or not. + */ +- (BOOL)canHandleURL:(NSURL *)URL; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.m new file mode 100644 index 00000000..5765f368 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.m @@ -0,0 +1,193 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +#import "FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthURLPresenter () +@end + +// Disable unguarded availability warnings because SFSafariViewController is been used throughout +// the code, including as an iVar, which cannot be simply excluded by @available check. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + +@implementation FIRAuthURLPresenter { + /** @var _isPresenting + @brief Whether or not some web-based content is being presented. + */ + BOOL _isPresenting; + + /** @var _callbackMatcher + @brief The callback URL matcher for the current presentation, if one is active. + */ + FIRAuthURLCallbackMatcher _Nullable _callbackMatcher; + + /** @var _safariViewController + @brief The SFSafariViewController used for the current presentation, if any. + */ + SFSafariViewController *_Nullable _safariViewController; + + /** @var _webViewController + @brief The FIRAuthWebViewController used for the current presentation, if any. + */ + FIRAuthWebViewController *_Nullable _webViewController; + + /** @var _UIDelegate + @brief The UIDelegate used to present the SFSafariViewController. + */ + id _UIDelegate; + + /** @var _completion + @brief The completion handler for the current presentaion, if one is active. + @remarks This variable is also used as a flag to indicate a presentation is active. + */ + FIRAuthURLPresentationCompletion _Nullable _completion; +} + +- (void)presentURL:(NSURL *)URL + UIDelegate:(nullable id)UIDelegate + callbackMatcher:(FIRAuthURLCallbackMatcher)callbackMatcher + completion:(FIRAuthURLPresentationCompletion)completion { + if (_isPresenting) { + // Unable to start a new presentation on top of another. + _completion(nil, [FIRAuthErrorUtils webContextAlreadyPresentedErrorWithMessage:nil]); + return; + } + _isPresenting = YES; + _callbackMatcher = callbackMatcher; + _completion = completion; + dispatch_async(dispatch_get_main_queue(), ^() { + self->_UIDelegate = UIDelegate ?: [FIRAuthDefaultUIDelegate defaultUIDelegate]; + if ([SFSafariViewController class]) { + self->_safariViewController = [[SFSafariViewController alloc] initWithURL:URL]; + self->_safariViewController.delegate = self; + [self->_UIDelegate presentViewController:self->_safariViewController + animated:YES + completion:nil]; + return; + } else { + self->_webViewController = [[FIRAuthWebViewController alloc] initWithURL:URL delegate:self]; + UINavigationController *navController = + [[UINavigationController alloc] initWithRootViewController:self->_webViewController]; + [self->_UIDelegate presentViewController:navController animated:YES completion:nil]; + } + }); +} + +- (BOOL)canHandleURL:(NSURL *)URL { + if (_isPresenting && _callbackMatcher && _callbackMatcher(URL)) { + [self finishPresentationWithURL:URL error:nil]; + return YES; + } + return NO; +} + +#pragma mark - SFSafariViewControllerDelegate + +- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller { + dispatch_async(FIRAuthGlobalWorkQueue(), ^() { + if (controller == self->_safariViewController) { + self->_safariViewController = nil; + // TODO:Ensure that the SFSafariViewController is actually removed from the screen before + // invoking finishPresentationWithURL:error: + [self finishPresentationWithURL:nil + error:[FIRAuthErrorUtils webContextCancelledErrorWithMessage:nil]]; + } + }); +} + +#pragma mark - FIRAuthwebViewControllerDelegate + +- (BOOL)webViewController:(FIRAuthWebViewController *)webViewController canHandleURL:(NSURL *)URL { + __block BOOL result = NO; + dispatch_sync(FIRAuthGlobalWorkQueue(), ^() { + if (webViewController == self->_webViewController) { + result = [self canHandleURL:URL]; + } + }); + return result; +} + +- (void)webViewControllerDidCancel:(FIRAuthWebViewController *)webViewController { + dispatch_async(FIRAuthGlobalWorkQueue(), ^() { + if (webViewController == self->_webViewController) { + [self finishPresentationWithURL:nil + error:[FIRAuthErrorUtils webContextCancelledErrorWithMessage:nil]]; + } + }); +} + +- (void)webViewController:(FIRAuthWebViewController *)webViewController + didFailWithError:(NSError *)error { + dispatch_async(FIRAuthGlobalWorkQueue(), ^() { + if (webViewController == self->_webViewController) { + [self finishPresentationWithURL:nil error:error]; + } + }); +} + +#pragma mark - Private methods + +/** @fn finishPresentationWithURL:error: + @brief Finishes the presentation for a given URL, if any. + @param URL The URL to finish presenting. + @param error The error with which to finish presenting, if any. + */ +- (void)finishPresentationWithURL:(nullable NSURL *)URL error:(nullable NSError *)error { + _callbackMatcher = nil; + id UIDelegate = _UIDelegate; + _UIDelegate = nil; + FIRAuthURLPresentationCompletion completion = _completion; + _completion = nil; + void (^finishBlock)(void) = ^() { + self->_isPresenting = NO; + completion(URL, error); + }; + SFSafariViewController *safariViewController = _safariViewController; + _safariViewController = nil; + FIRAuthWebViewController *webViewController = _webViewController; + _webViewController = nil; + if (safariViewController || webViewController) { + dispatch_async(dispatch_get_main_queue(), ^() { + [UIDelegate dismissViewControllerAnimated:YES + completion:^() { + dispatch_async(FIRAuthGlobalWorkQueue(), finishBlock); + }]; + }); + } else { + finishBlock(); + } +} + +#pragma clang diagnostic pop // ignored "-Wunguarded-availability" + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h new file mode 100644 index 00000000..7a3d080b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h @@ -0,0 +1,102 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAuthRequestConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRFetchAuthDomainCallback + @brief The callback invoked at the end of the flow to fetch the Auth domain. + @param authDomain The Auth domain. + @param error The error that occurred while fetching the auth domain, if any. + */ +typedef void (^FIRFetchAuthDomainCallback)(NSString *_Nullable authDomain, + NSError *_Nullable error); + +/** @class FIRAuthURLUtils + @brief A utility class used to facilitate the creation of auth related URLs. + */ +@interface FIRAuthWebUtils : NSObject + +/** @fn randomStringWithLength: + @brief Generates a random string of a specified length. + */ ++ (NSString *)randomStringWithLength:(NSUInteger)length; + +/** @fn isCallbackSchemeRegisteredForCustomURLScheme: + @brief Checks whether or not the provided custom URL scheme has been registered by the app. + @param URLScheme The custom URL scheme to be checked against all custom URL schemes registered + by the app. + @return whether or not the provided custom URL scheme has been registered by the app. + */ ++ (BOOL)isCallbackSchemeRegisteredForCustomURLScheme:(NSString *)URLScheme; + +/** @fn isExpectedCallbackURL:eventID:authType + @brief Parses a URL into all available query items. + @param URL The actual callback URL. + @param eventID The expected event ID. + @param authType The expected auth type. + @param callbackScheme The expected callback custom scheme. + @return Whether or not the actual callback URL matches the expected callback URL. + */ ++ (BOOL)isExpectedCallbackURL:(nullable NSURL *)URL + eventID:(NSString *)eventID + authType:(NSString *)authType + callbackScheme:(NSString *)callbackScheme; + +/** @fn fetchAuthDomainWithCompletion:completion: + @brief Fetches the auth domain associated with the Firebase Project. + @param completion The callback invoked after the auth domain has been constructed or an error + has been encountered. + */ ++ (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + completion:(FIRFetchAuthDomainCallback)completion; + +/** @fn queryItemValue:from: + @brief Utility function to get a value from a NSURLQueryItem array. + @param name The key. + @param queryList The NSURLQueryItem array. + @return The value for the key. + */ + ++ (nullable NSString *)queryItemValue:(NSString *)name from:(NSArray *)queryList; + +/** @fn dictionaryWithHttpArgumentsString: + @brief Utility function to get a dictionary from a http argument string. + @param argString The http argument string. + @return The resulting dictionary of query arguments. + */ ++ (NSDictionary *)dictionaryWithHttpArgumentsString:(NSString *)argString; + +/** @fn stringByUnescapingFromURLArgument:from: + @brief Utility function to get a string by unescapting URL arguments. + @param argument The argument string. + @return The resulting string after unescaping URL argument. + */ ++ (NSString *)stringByUnescapingFromURLArgument:(NSString *)argument; + +/** @fn parseURL: + @brief Parses an incoming URL into all available query items. + @param urlString The url to be parsed. + @return A dictionary of available query items in the target URL. + */ ++ (NSDictionary *)parseURL:(NSString *)urlString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.m new file mode 100644 index 00000000..f117bb18 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.m @@ -0,0 +1,205 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h" + +#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h" +#import "FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthWebUtils + ++ (NSArray *)supportedAuthDomains { + return @[ @"firebaseapp.com", @"web.app" ]; +} + ++ (NSString *)randomStringWithLength:(NSUInteger)length { + NSMutableString *randomString = [[NSMutableString alloc] init]; + for (int i = 0; i < length; i++) { + [randomString + appendString:[NSString stringWithFormat:@"%c", 'a' + arc4random_uniform('z' - 'a' + 1)]]; + } + return randomString; +} + ++ (BOOL)isCallbackSchemeRegisteredForCustomURLScheme:(NSString *)URLScheme { + NSString *expectedCustomScheme = [URLScheme lowercaseString]; + NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + NSArray *urlTypeSchemes = urlType[@"CFBundleURLSchemes"]; + for (NSString *urlTypeScheme in urlTypeSchemes) { + if ([urlTypeScheme.lowercaseString isEqualToString:expectedCustomScheme]) { + return YES; + } + } + } + return NO; +} + ++ (BOOL)isExpectedCallbackURL:(nullable NSURL *)URL + eventID:(NSString *)eventID + authType:(NSString *)authType + callbackScheme:(NSString *)callbackScheme { + if (!URL) { + return NO; + } + NSURLComponents *actualURLComponents = [NSURLComponents componentsWithURL:URL + resolvingAgainstBaseURL:NO]; + actualURLComponents.query = nil; + actualURLComponents.fragment = nil; + + NSURLComponents *expectedURLComponents = [[NSURLComponents alloc] init]; + expectedURLComponents.scheme = callbackScheme; + expectedURLComponents.host = @"firebaseauth"; + expectedURLComponents.path = @"/link"; + + if (![expectedURLComponents.URL isEqual:actualURLComponents.URL]) { + return NO; + } + NSDictionary *URLQueryItems = + [self dictionaryWithHttpArgumentsString:URL.query]; + NSURL *deeplinkURL = [NSURL URLWithString:URLQueryItems[@"deep_link_id"]]; + NSDictionary *deeplinkQueryItems = + [self dictionaryWithHttpArgumentsString:deeplinkURL.query]; + if ([deeplinkQueryItems[@"authType"] isEqualToString:authType] && + [deeplinkQueryItems[@"eventId"] isEqualToString:eventID]) { + return YES; + } + return NO; +} + ++ (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration + completion:(FIRFetchAuthDomainCallback)completion { + FIRGetProjectConfigRequest *request = + [[FIRGetProjectConfigRequest alloc] initWithRequestConfiguration:requestConfiguration]; + + [FIRAuthBackend + getProjectConfig:request + callback:^(FIRGetProjectConfigResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + completion(nil, error); + return; + } + // Look up an authorized domain ends with one of the supportedAuthDomains. + // The sequence of supportedAuthDomains matters. ("firebaseapp.com", "web.app") + // The searching ends once the first valid suportedAuthDomain is found. + NSString *authDomain; + for (NSString *domain in response.authorizedDomains) { + for (NSString *suportedAuthDomain in [self supportedAuthDomains]) { + NSInteger index = domain.length - suportedAuthDomain.length; + if (index >= 2) { + if ([domain hasSuffix:suportedAuthDomain] && + domain.length >= suportedAuthDomain.length + 2) { + authDomain = domain; + break; + } + } + } + if (authDomain != nil) { + break; + } + } + if (!authDomain.length) { + completion(nil, [FIRAuthErrorUtils + unexpectedErrorResponseWithDeserializedResponse:response]); + return; + } + completion(authDomain, nil); + }]; +} + +/** @fn queryItemValue:from: + @brief Utility function to get a value from a NSURLQueryItem array. + @param name The key. + @param queryList The NSURLQueryItem array. + @return The value for the key. + */ ++ (nullable NSString *)queryItemValue:(NSString *)name from:(NSArray *)queryList { + for (NSURLQueryItem *item in queryList) { + if ([item.name isEqualToString:name]) { + return item.value; + } + } + return nil; +} + ++ (NSDictionary *)dictionaryWithHttpArgumentsString:(NSString *)argString { + NSMutableDictionary *ret = [NSMutableDictionary dictionary]; + NSArray *components = [argString componentsSeparatedByString:@"&"]; + NSString *component; + // Use reverse order so that the first occurrence of a key replaces + // those subsequent. + for (component in [components reverseObjectEnumerator]) { + if (component.length == 0) continue; + NSRange pos = [component rangeOfString:@"="]; + NSString *key; + NSString *val; + if (pos.location == NSNotFound) { + key = [self stringByUnescapingFromURLArgument:component]; + val = @""; + } else { + key = [self stringByUnescapingFromURLArgument:[component substringToIndex:pos.location]]; + val = [self stringByUnescapingFromURLArgument:[component substringFromIndex:pos.location + + pos.length]]; + } + // returns nil on invalid UTF8 and NSMutableDictionary raises an exception when passed nil + // values. + if (!key) key = @""; + if (!val) val = @""; + [ret setObject:val forKey:key]; + } + return ret; +} + ++ (NSString *)stringByUnescapingFromURLArgument:(NSString *)argument { + NSMutableString *resultString = [NSMutableString stringWithString:argument]; + [resultString replaceOccurrencesOfString:@"+" + withString:@" " + options:NSLiteralSearch + range:NSMakeRange(0, [resultString length])]; + return [resultString stringByRemovingPercentEncoding]; +} + ++ (NSDictionary *)parseURL:(NSString *)urlString { + NSString *linkURL = [NSURLComponents componentsWithString:urlString].query; + if (!linkURL) { + return @{}; + } + NSArray *URLComponents = [linkURL componentsSeparatedByString:@"&"]; + NSMutableDictionary *queryItems = + [[NSMutableDictionary alloc] initWithCapacity:URLComponents.count]; + for (NSString *component in URLComponents) { + NSRange equalRange = [component rangeOfString:@"="]; + if (equalRange.location != NSNotFound) { + NSString *queryItemKey = + [[component substringToIndex:equalRange.location] stringByRemovingPercentEncoding]; + NSString *queryItemValue = + [[component substringFromIndex:equalRange.location + 1] stringByRemovingPercentEncoding]; + if (queryItemKey && queryItemValue) { + queryItems[queryItemKey] = queryItemValue; + } + } + } + return queryItems; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.h new file mode 100644 index 00000000..bd50309b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FIRAuthWebView + @brief A class reponsible for creating a WKWebView for use within Firebase Auth. + */ +@interface FIRAuthWebView : UIView + +/** @property webView + * @brief The web view. + */ +@property(nonatomic, weak) WKWebView *webView; + +/** @property spinner + * @brief The spinner that indicates web view loading. + */ +@property(nonatomic, weak) UIActivityIndicatorView *spinner; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.m new file mode 100644 index 00000000..6807dbff --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebView.m @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebView.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FIRAuthWebView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor whiteColor]; + [self initializeSubviews]; + } + return self; +} + +/** @fn initializeSubviews + @brief Initializes the subviews of this view. + */ +- (void)initializeSubviews { + WKWebView *webView = [self createWebView]; + UIActivityIndicatorView *spinner = [self createSpinner]; + + // The order of the following controls z-order. + [self addSubview:webView]; + [self addSubview:spinner]; + + [self layoutSubviews]; + _webView = webView; + _spinner = spinner; +} + +- (void)layoutSubviews { + CGFloat height = self.bounds.size.height; + CGFloat width = self.bounds.size.width; + _webView.frame = CGRectMake(0, 0, width, height); + _spinner.center = _webView.center; +} + +/** @fn createWebView + @brief Creates a web view to be used by this view. + @return The newly created web view. + */ +- (WKWebView *)createWebView { + WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero]; + // Trickery to make the web view not do weird things (like showing a black background when + // the prompt in the navigation bar animates changes.) + webView.opaque = NO; + webView.backgroundColor = [UIColor clearColor]; + webView.scrollView.opaque = NO; + webView.scrollView.backgroundColor = [UIColor clearColor]; + webView.scrollView.bounces = NO; + webView.scrollView.alwaysBounceVertical = NO; + webView.scrollView.alwaysBounceHorizontal = NO; + return webView; +} + +/** @fn createSpinner + @brief Creates a spinner to be used by this view. + @return The newly created spinner. + */ +- (UIActivityIndicatorView *)createSpinner { + UIActivityIndicatorViewStyle spinnerStyle; +#if defined(TARGET_OS_MACCATALYST) + if (@available(iOS 13.0, *)) { + spinnerStyle = UIActivityIndicatorViewStyleMedium; + } else { +// iOS 13 deprecation +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + spinnerStyle = UIActivityIndicatorViewStyleGray; +#pragma clang diagnostic pop + } +#else + spinnerStyle = UIActivityIndicatorViewStyleGray; +#endif + UIActivityIndicatorView *spinner = + [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:spinnerStyle]; + return spinner; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h new file mode 100644 index 00000000..8c75b467 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import + +@class FIRAuthWebViewController; + +NS_ASSUME_NONNULL_BEGIN + +/** @protocol FIRAuthWebViewControllerDelegate + @brief Defines a delegate for FIRAuthWebViewController + */ +@protocol FIRAuthWebViewControllerDelegate + +/** @fn webViewController:canHandleURL: + @brief Determines if a URL should be handled by the delegate. + @param URL The URL to handle. + @return Whether the URL could be handled or not. + */ +- (BOOL)webViewController:(FIRAuthWebViewController *)webViewController canHandleURL:(NSURL *)URL; + +/** @fn webViewControllerDidCancel: + @brief Notifies the delegate that the web view controller is being cancelled by the user. + @param webViewController The web view controller in question. + */ +- (void)webViewControllerDidCancel:(FIRAuthWebViewController *)webViewController; + +/** @fn webViewController:didFailWithError: + @brief Notifies the delegate that the web view controller failed to load a page. + @param webViewController The web view controller in question. + @param error The error that has occurred. + */ +- (void)webViewController:(FIRAuthWebViewController *)webViewController + didFailWithError:(NSError *)error; + +@end + +/** @class FIRAuthWebViewController + @brief Reponsible for creating a UIViewController for presenting a FIRAutWebView. + */ +@interface FIRAuthWebViewController : UIViewController + +/** @fn initWithNibName:bundle: + * @brief Please call initWithURL:delegate: + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil + bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE; + +/** @fn initWithCoder: + * @brief Please call initWithURL:delegate: + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; + +- (instancetype)initWithURL:(NSURL *)URL + delegate:(__weak id)delegate + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.m new file mode 100644 index 00000000..65d67a65 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.m @@ -0,0 +1,118 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if TARGET_OS_IOS + +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebView.h" +#import "FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRAuthWebViewController () +@end + +@implementation FIRAuthWebViewController { + /** @var _URL + @brief The initial URL to display. + */ + NSURL *_URL; + + /** @var _delegate + @brief The delegate to call. + */ + __weak id _delegate; + + /** @var _webView; + @brief The web view instance for easier access. + */ + __weak FIRAuthWebView *_webView; +} + +- (instancetype)initWithURL:(NSURL *)URL + delegate:(__weak id)delegate { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + _URL = URL; + _delegate = delegate; + } + return self; +} + +#pragma mark - Lifecycle + +- (void)loadView { + FIRAuthWebView *webView = [[FIRAuthWebView alloc] initWithFrame:[UIScreen mainScreen].bounds]; + webView.webView.navigationDelegate = self; + self.view = webView; + _webView = webView; + self.navigationItem.leftBarButtonItem = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancel)]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + // Loads the requested URL in the web view. + [_webView.webView loadRequest:[NSURLRequest requestWithURL:_URL]]; +} + +#pragma mark - UI Targets + +- (void)cancel { + [_delegate webViewControllerDidCancel:self]; +} + +#pragma mark - WKNavigationDelegate + +- (void)webView:(WKWebView *)webView + decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction + decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + [_delegate webViewController:self canHandleURL:navigationAction.request.URL]; + decisionHandler(WKNavigationActionPolicyAllow); +} + +- (void)webView:(WKWebView *)webView + didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation { + _webView.spinner.hidden = NO; + [_webView.spinner startAnimating]; +} + +- (void)webView:(WKWebView *)webView + didFinishNavigation:(null_unspecified WKNavigation *)navigation { + _webView.spinner.hidden = YES; + [_webView.spinner stopAnimating]; +} + +- (void)webView:(WKWebView *)webView + didFailNavigation:(null_unspecified WKNavigation *)navigation + withError:(NSError *)error { + if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { + // It's okay for the page to be redirected before it is completely loaded. See b/32028062 . + return; + } + // Forward notification to our delegate. + [self webView:webView didFinishNavigation:navigation]; + [_delegate webViewController:self didFailWithError:error]; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h new file mode 100644 index 00000000..114cbfd9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSData (FIRBase64) + +/** @fn fir_base64URLEncodedStringWithOptions: + @brief Get a web safe base64 encoded string + @param options The base64 encoding options + */ +- (NSString *)fir_base64URLEncodedStringWithOptions:(NSDataBase64EncodingOptions)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.m b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.m new file mode 100644 index 00000000..0afc53b8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseAuth/Sources/Utilities/NSData+FIRBase64.m @@ -0,0 +1,33 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation NSData (FIRBase64) + +- (NSString *)fir_base64URLEncodedStringWithOptions:(NSDataBase64EncodingOptions)options { + NSString *string = [self base64EncodedStringWithOptions:options]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + string = [string stringByReplacingOccurrencesOfString:@"=" withString:@""]; + return string; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRAppInternal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponent.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentContainer.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentType.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRDependency.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrorCode.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrors.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLibrary.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLogger.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIROptionsInternal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/MyExperiences copy/Pods/FirebaseAuth/Interop/Auth/Public/FIRAuthInterop.h b/MyExperiences copy/Pods/FirebaseAuth/Interop/Auth/Public/FIRAuthInterop.h new file mode 100644 index 00000000..a33da7c9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/Interop/Auth/Public/FIRAuthInterop.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRAuthInterop_h +#define FIRAuthInterop_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRTokenCallback + @brief The type of block which gets called when a token is ready. + */ +typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(TokenCallback); + +/// Common methods for Auth interoperability. +NS_SWIFT_NAME(AuthInterop) +@protocol FIRAuthInterop + +/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired. +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback; + +/// Get the current Auth user's UID. Returns nil if there is no user signed in. +- (nullable NSString *)getUserID; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRAuthInterop_h */ diff --git a/MyExperiences copy/Pods/FirebaseAuth/LICENSE b/MyExperiences copy/Pods/FirebaseAuth/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseAuth/README.md b/MyExperiences copy/Pods/FirebaseAuth/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseAuth/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h new file mode 100644 index 00000000..6429ac70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// Values stored in analyticsEnabledState. Never alter these constants since they must match with +/// values persisted to disk. +typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) { + // 0 is the default value for keys not found stored in persisted config, so it cannot represent + // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet. + kFIRAnalyticsEnabledStateNotSet = 0, + kFIRAnalyticsEnabledStateSetYes = 1, + kFIRAnalyticsEnabledStateSetNo = 2, +}; + +/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads +/// measurementEnabledState using this same key. +static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey = + @"/google/measurement/measurement_enabled_state"; + +static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification = + @"FIRAnalyticsConfigurationSetEnabledNotification"; +static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification = + @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification"; +static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification = + @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification"; + +@interface FIRAnalyticsConfiguration : NSObject + +/// Returns the shared instance of FIRAnalyticsConfiguration. ++ (FIRAnalyticsConfiguration *)sharedInstance; + +// Sets whether analytics collection is enabled for this app on this device. This setting is +// persisted across app sessions. By default it is enabled. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist +/// the value or not. The setting should not be persisted if being set by the global data collection +/// flag. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist; + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m new file mode 100644 index 00000000..07c786cb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m @@ -0,0 +1,62 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +@implementation FIRAnalyticsConfiguration +#pragma clang diagnostic pop + ++ (FIRAnalyticsConfiguration *)sharedInstance { + static FIRAnalyticsConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRAnalyticsConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (void)postNotificationName:(NSString *)name value:(id)value { + if (!name.length || !value) { + return; + } + [[NSNotificationCenter defaultCenter] postNotificationName:name + object:self + userInfo:@{name : value}]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled { + [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist { + // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO. + FIRAnalyticsEnabledState analyticsEnabledState = + analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo; + if (shouldPersist) { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:@(analyticsEnabledState) + forKey:kFIRAPersistedConfigMeasurementEnabledStateKey]; + [userDefaults synchronize]; + } + + [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification + value:@(analyticsCollectionEnabled)]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m new file mode 100644 index 00000000..4dfbfa83 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m @@ -0,0 +1,938 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#if __has_include() +#import +#endif + +#if __has_include() +#import +#endif + +#import "FirebaseCore/Sources/Public/FIRApp.h" + +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRComponentContainerInternal.h" +#import "FirebaseCore/Sources/FIRConfigurationInternal.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +#import + +#import + +// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics +// pod to a Core dependency. These symbols are not used and should be deleted after the transition. +NSString *const kFIRServiceAdMob; +NSString *const kFIRServiceAuth; +NSString *const kFIRServiceAuthUI; +NSString *const kFIRServiceCrash; +NSString *const kFIRServiceDatabase; +NSString *const kFIRServiceDynamicLinks; +NSString *const kFIRServiceFirestore; +NSString *const kFIRServiceFunctions; +NSString *const kFIRServiceInstanceID; +NSString *const kFIRServiceInvites; +NSString *const kFIRServiceMessaging; +NSString *const kFIRServiceMeasurement; +NSString *const kFIRServicePerformance; +NSString *const kFIRServiceRemoteConfig; +NSString *const kFIRServiceStorage; +NSString *const kGGLServiceAnalytics; +NSString *const kGGLServiceSignIn; + +NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT"; +NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification"; +NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification"; +NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; +NSString *const kFIRAppNameKey = @"FIRAppNameKey"; +NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; + +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseDataCollectionDefaultEnabled"; + +NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; + +NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; +NSString *const kFIRAppDiagnosticsErrorKey = @"Error"; +NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; +NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; +NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; +NSString *const kFIRAppDiagnosticsApplePlatformPrefix = @"apple-platform"; + +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey = + @"FIRAuthStateDidChangeInternalNotificationUIDKey"; + +/** + * The URL to download plist files. + */ +static NSString *const kPlistURL = @"https://console.firebase.google.com/"; + +/** + * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle + * events from Core. + */ +static NSMutableArray> *sRegisteredAsConfigurable; + +@interface FIRApp () + +#ifdef DEBUG +@property(nonatomic) BOOL alreadyOutputDataCollectionFlag; +#endif // DEBUG + +@end + +@implementation FIRApp + +// This is necessary since our custom getter prevents `_options` from being created. +@synthesize options = _options; + +static NSMutableDictionary *sAllApps; +static FIRApp *sDefaultApp; +static NSMutableDictionary *sLibraryVersions; +static dispatch_once_t sFirebaseUserAgentOnceToken; + ++ (void)configure { + FIROptions *options = [FIROptions defaultOptions]; + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find " + @"a valid GoogleService-Info.plist in your project. Please download one " + @"from %@.", + kPlistURL]; + } + [FIRApp configureWithOptions:options]; +#if TARGET_OS_OSX || TARGET_OS_TV + FIRLogNotice(kFIRLoggerCore, @"I-COR000028", + @"tvOS and macOS SDK support is not part of the official Firebase product. " + @"Instead they are community supported. Details at " + @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md."); +#endif +} + ++ (void)configureWithOptions:(FIROptions *)options { + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Options is nil. Please pass a valid options."]; + } + [FIRApp configureWithName:kFIRDefaultAppName options:options]; +} + ++ (NSCharacterSet *)applicationNameAllowedCharacters { + static NSCharacterSet *applicationNameAllowedCharacters; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableCharacterSet *allowedNameCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedNameCharacters addCharactersInString:@"-_"]; + applicationNameAllowedCharacters = [allowedNameCharacters copy]; + }); + return applicationNameAllowedCharacters; +} + ++ (void)configureWithName:(NSString *)name options:(FIROptions *)options { + if (!name || !options) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."]; + } + if (name.length == 0) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."]; + } + + if ([name isEqualToString:kFIRDefaultAppName]) { + if (sDefaultApp) { + // The default app already exists. Handle duplicate `configure` calls and return. + [self appWasConfiguredTwice:sDefaultApp usingOptions:options]; + return; + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app."); + } else { + // Validate the app name and ensure it hasn't been configured already. + NSCharacterSet *nameCharacters = [NSCharacterSet characterSetWithCharactersInString:name]; + + if (![[self applicationNameAllowedCharacters] isSupersetOfSet:nameCharacters]) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App name can only contain alphanumeric, " + @"hyphen (-), and underscore (_) characters"]; + } + + @synchronized(self) { + if (sAllApps && sAllApps[name]) { + // The app already exists. Handle a duplicate `configure` call and return. + [self appWasConfiguredTwice:sAllApps[name] usingOptions:options]; + return; + } + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name); + } + + @synchronized(self) { + FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options]; + if (app.isDefaultApp) { + sDefaultApp = app; + } + + [FIRApp addAppToAppDictionary:app]; + + // The FIRApp instance is ready to go, `sDefaultApp` is assigned, other SDKs are now ready to be + // instantiated. + [app.container instantiateEagerComponents]; + [FIRApp sendNotificationsToSDKs:app]; + } +} + +/// Called when `configure` has been called multiple times for the same app. This can either throw +/// an exception (most cases) or ignore the duplicate configuration in situations where it's allowed +/// like an extension. ++ (void)appWasConfiguredTwice:(FIRApp *)app usingOptions:(FIROptions *)options { + // Only extensions should potentially be able to call `configure` more than once. + if (![GULAppEnvironmentUtil isAppExtension]) { + // Throw an exception since this is now an invalid state. + if (app.isDefaultApp) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Default app has already been configured."]; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } + } + + // In an extension, the entry point could be called multiple times. As long as the options are + // identical we should allow multiple `configure` calls. + if ([options isEqual:app.options]) { + // Everything is identical but the extension's lifecycle triggered `configure` twice. + // Ignore duplicate calls and return since everything should still be in a valid state. + FIRLogDebug(kFIRLoggerCore, @"I-COR000035", + @"Ignoring second `configure` call in an extension."); + return; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } +} + ++ (FIRApp *)defaultApp { + if (sDefaultApp) { + return sDefaultApp; + } + FIRLogError(kFIRLoggerCore, @"I-COR000003", + @"The default Firebase app has not yet been " + @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your " + @"application initialization. Read more: https://goo.gl/ctyzm8."); + return nil; +} + ++ (FIRApp *)appNamed:(NSString *)name { + @synchronized(self) { + if (sAllApps) { + FIRApp *app = sAllApps[name]; + if (app) { + return app; + } + } + FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name); + return nil; + } +} + ++ (NSDictionary *)allApps { + @synchronized(self) { + if (!sAllApps) { + FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet."); + } + return [sAllApps copy]; + } +} + +// Public only for tests ++ (void)resetApps { + @synchronized(self) { + sDefaultApp = nil; + [sAllApps removeAllObjects]; + sAllApps = nil; + [sLibraryVersions removeAllObjects]; + sLibraryVersions = nil; + sFirebaseUserAgentOnceToken = 0; + } +} + +- (void)deleteApp:(FIRAppVoidBoolCallback)completion { + @synchronized([self class]) { + if (sAllApps && sAllApps[self.name]) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); + + // Remove all registered libraries from the container to avoid creating new instances. + [self.container removeAllComponents]; + // Remove all cached instances from the container before deleting the app. + [self.container removeAllCachedInstances]; + + [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; + if ([self.name isEqualToString:kFIRDefaultAppName]) { + sDefaultApp = nil; + } + NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name}; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification + object:[self class] + userInfo:appInfoDict]; + completion(YES); + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist."); + completion(NO); + } + } +} + ++ (void)addAppToAppDictionary:(FIRApp *)app { + if (!sAllApps) { + sAllApps = [NSMutableDictionary dictionary]; + } + if ([app configureCore]) { + sAllApps[app.name] = app; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in " + @"GoogleService-Info.plist or set in the customized options."]; + } +} + +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options { + self = [super init]; + if (self) { + _name = [name copy]; + _options = [options copy]; + _options.editingLocked = YES; + _isDefaultApp = [name isEqualToString:kFIRDefaultAppName]; + _container = [[FIRComponentContainer alloc] initWithApp:self]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)configureCore { + [self checkExpectedBundleID]; + if (![self isAppIDValid]) { + return NO; + } + + [self logCoreTelemetryIfEnabled]; + +#if TARGET_OS_IOS + // Initialize the Analytics once there is a valid options under default app. Analytics should + // always initialize first by itself before the other SDKs. + if ([self.name isEqualToString:kFIRDefaultAppName]) { + Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics"); + if (firAnalyticsClass) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:); +#pragma clang diagnostic pop + if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [firAnalyticsClass performSelector:startWithConfigurationSelector + withObject:[FIRConfiguration sharedInstance].analyticsConfiguration + withObject:_options]; +#pragma clang diagnostic pop + } + } + } +#endif + + [self subscribeForAppDidBecomeActiveNotifications]; + + return YES; +} + +- (FIROptions *)options { + return [_options copy]; +} + +- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled { +#ifdef DEBUG + FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.", + dataCollectionDefaultEnabled ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; +#endif // DEBUG + + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key]; + + // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set + // within FIROptions and change the Analytics value if necessary. Analytics only works with the + // default app, so return if this isn't the default app. + if (!self.isDefaultApp) { + return; + } + + // Check if the Analytics flag is explicitly set. If so, no further actions are necessary. + if ([self.options isAnalyticsCollectionExplicitlySet]) { + return; + } + + // The Analytics flag has not been explicitly set, so update with the value being set. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[FIRAnalyticsConfiguration sharedInstance] + setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled + persistSetting:NO]; +#pragma clang diagnostic pop +} + +- (BOOL)isDataCollectionDefaultEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.", + [defaultsObject boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.", + [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [collectionEnabledPlistValue boolValue]; + } + +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set."); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return YES; +} + +#pragma mark - private + ++ (void)sendNotificationsToSDKs:(FIRApp *)app { + // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`. + NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp]; + NSDictionary *appInfoDict = @{ + kFIRAppNameKey : app.name, + kFIRAppIsDefaultAppKey : isDefaultApp, + kFIRGoogleAppIDKey : app.options.googleAppID + }; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification + object:self + userInfo:appInfoDict]; + + // This is the new way of sending information to SDKs. + // TODO: Do we want this on a background thread, maybe? + @synchronized(self) { + for (Class library in sRegisteredAsConfigurable) { + [library configureWithApp:app]; + } + } +} + ++ (NSError *)errorForMissingOptions { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : + @"Unable to parse GoogleService-Info.plist in order to configure services.", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidPlistFile + userInfo:errorDict]; +} + ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", service]; + NSDictionary *errorDict = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + return [NSError errorWithDomain:domain code:code userInfo:errorDict]; +} + ++ (NSError *)errorForInvalidAppID { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : @"Unable to validate Google App ID", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the " + @"customized options." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidAppID + userInfo:errorDict]; +} + ++ (BOOL)isDefaultAppConfigured { + return (sDefaultApp != nil); +} + ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version { + // Create the set of characters which aren't allowed, only if this feature is used. + NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedSet addCharactersInString:@"-_."]; + NSCharacterSet *disallowedSet = [allowedSet invertedSet]; + // Make sure the library name and version strings do not contain unexpected characters, and + // add the name/version pair to the dictionary. + if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound && + [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) { + @synchronized(self) { + if (!sLibraryVersions) { + sLibraryVersions = [[NSMutableDictionary alloc] init]; + } + sLibraryVersions[name] = version; + } + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000027", + @"The library name (%@) or version number (%@) contain invalid characters. " + @"Only alphanumeric, dash, underscore and period characters are allowed.", + name, version); + } +} + ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version { + // This is called at +load time, keep the work to a minimum. + + // Ensure the class given conforms to the proper protocol. + if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] || + ![(Class)library respondsToSelector:@selector(componentsToRegister)]) { + [NSException raise:NSInvalidArgumentException + format:@"Class %@ attempted to register components, but it does not conform to " + @"`FIRLibrary or provide a `componentsToRegister:` method.", + library]; + } + + [FIRComponentContainer registerAsComponentRegistrant:library]; + if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRegisteredAsConfigurable = [[NSMutableArray alloc] init]; + }); + @synchronized(self) { + [sRegisteredAsConfigurable addObject:library]; + } + } + [self registerLibrary:name withVersion:version]; +} + ++ (NSString *)firebaseUserAgent { + @synchronized(self) { + dispatch_once(&sFirebaseUserAgentOnceToken, ^{ + // Report FirebaseCore version for useragent string + [FIRApp registerLibrary:@"fire-ios" + withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]]; + + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *xcodeVersion = info[@"DTXcodeBuild"]; + NSString *sdkVersion = info[@"DTSDKBuild"]; + if (xcodeVersion) { + [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion]; + } + if (sdkVersion) { + [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion]; + } + + NSString *swiftFlagValue = [self hasSwiftRuntime] ? @"true" : @"false"; + [FIRApp registerLibrary:@"swift" withVersion:swiftFlagValue]; + + [FIRApp registerLibrary:kFIRAppDiagnosticsApplePlatformPrefix + withVersion:[self applePlatform]]; + }); + + NSMutableArray *libraries = + [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count]; + for (NSString *libraryName in sLibraryVersions) { + [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName, + sLibraryVersions[libraryName]]]; + } + [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + return [libraries componentsJoinedByString:@" "]; + } +} + ++ (BOOL)hasSwiftRuntime { + // The class + // [Swift._SwiftObject](https://github.com/apple/swift/blob/5eac3e2818eb340b11232aff83edfbd1c307fa03/stdlib/public/runtime/SwiftObject.h#L35) + // is a part of Swift runtime, so it should be present if Swift runtime is available. + + BOOL hasSwiftRuntime = + objc_lookUpClass("Swift._SwiftObject") != nil || + // Swift object class name before + // https://github.com/apple/swift/commit/9637b4a6e11ddca72f5f6dbe528efc7c92f14d01 + objc_getClass("_TtCs12_SwiftObject") != nil; + + return hasSwiftRuntime; +} + ++ (NSString *)applePlatform { + NSString *applePlatform = @"unknown"; + + // When a Catalyst app is run on macOS then both `TARGET_OS_MACCATALYST` and `TARGET_OS_IOS` are + // `true`, which means the condition list is order-sensitive. +#if TARGET_OS_MACCATALYST + applePlatform = @"maccatalyst"; +#elif TARGET_OS_IOS + applePlatform = @"ios"; +#elif TARGET_OS_TV + applePlatform = @"tvos"; +#elif TARGET_OS_OSX + applePlatform = @"macos"; +#elif TARGET_OS_WATCH + applePlatform = @"watchos"; +#endif + + return applePlatform; +} + +- (void)checkExpectedBundleID { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *expectedBundleID = [self expectedBundleID]; + // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for + // backward compatibility. + if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID + inBundles:bundles]) { + FIRLogError(kFIRLoggerCore, @"I-COR000008", + @"The project's Bundle ID is inconsistent with " + @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are " + @"using a customized options. To ensure that everything can be configured " + @"correctly, you may need to make the Bundle IDs consistent. To continue with this " + @"plist file, you may change your app's bundle identifier to '%@'. Or you can " + @"download a new configuration file that matches your bundle identifier from %@ " + @"and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + } +} + +#pragma mark - private - App ID Validation + +/** + * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. + * This is the main method for validating app ID. + * + * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + */ +- (BOOL)isAppIDValid { + NSString *appID = _options.googleAppID; + BOOL isValid = [FIRApp validateAppID:appID]; + if (!isValid) { + NSString *expectedBundleID = [self expectedBundleID]; + FIRLogError(kFIRLoggerCore, @"I-COR000009", + @"The GOOGLE_APP_ID either in the plist file " + @"'%@.%@' or the one set in the customized options is invalid. If you are using " + @"the plist file, use the iOS version of bundle identifier to download the file, " + @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle " + @"identifier to '%@'. Or you can download a new configuration file that matches " + @"your bundle identifier from %@ and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + }; + return isValid; +} + ++ (BOOL)validateAppID:(NSString *)appID { + // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not + // have a valid fingerprint, otherwise we just warn about the potential issue. + if (!appID.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + NSString *appIDVersion; + if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] + intoString:&appIDVersion]) { + return NO; + } + + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + NSArray *knownVersions = @[ @"1" ]; + if (![knownVersions containsObject:appIDVersion]) { + // Permit unknown yet properly formatted app ID versions. + FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion); + return YES; + } + + if (![self validateAppIDFormat:appID withVersion:appIDVersion]) { + return NO; + } + + if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + return NO; + } + + return YES; +} + ++ (NSString *)actualBundleID { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +/** + * Validates that the format of the app ID string is what is expected based on the supplied version. + * The version must end in ":". + * + * For v1 app ids the format is expected to be + * '::ios:'. + * + * This method does not verify that the contents of the app id are correct, just that they fulfill + * the expected format. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected format, NO otherwise. + */ ++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { + if (!appID.length || !version.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + // Skip version part + // '**::ios:' + if (![stringScanner scanString:version intoString:NULL]) { + // The version part is missing or mismatched + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '*:*:ios:' + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':**:ios:'. + NSInteger projectNumber = NSNotFound; + if (![stringScanner scanInteger:&projectNumber]) { + // NO project number found. + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':*:*ios:'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The project number must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::*ios*:'. + NSString *platform; + if (![stringScanner scanUpToString:@":" intoString:&platform]) { + return NO; + } + + if (![platform isEqualToString:@"ios"]) { + // The platform must be @"ios" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios*:*'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The platform must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios:**'. + unsigned long long fingerprint = NSNotFound; + if (![stringScanner scanHexLongLong:&fingerprint]) { + // Fingerprint part is missing + return NO; + } + + if (!stringScanner.isAtEnd) { + // There are not allowed characters in the fingerprint part + return NO; + } + + return YES; +} + +/** + * Validates that the fingerprint of the app ID string is what is expected based on the supplied + * version. + * + * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * otherwise. + */ ++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { + // Extract the supplied fingerprint from the supplied app ID. + // This assumes the app ID format is the same for all known versions below. If the app ID format + // changes in future versions, the tokenizing of the app ID format will need to take into account + // the version of the app ID. + NSArray *components = [appID componentsSeparatedByString:@":"]; + if (components.count != 4) { + return NO; + } + + NSString *suppliedFingerprintString = components[3]; + if (!suppliedFingerprintString.length) { + return NO; + } + + uint64_t suppliedFingerprint; + NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; + if (![scanner scanHexLongLong:&suppliedFingerprint]) { + return NO; + } + + if ([version isEqual:@"1"]) { + // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated. + return YES; + } + + // Unknown version. + return NO; +} + +- (NSString *)expectedBundleID { + return _options.bundleID; +} + +// end App ID validation + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error { + // Do nothing. Please remove calls to this method. +} +#pragma clang diagnostic pop + +#pragma mark - App Life Cycle + +- (void)subscribeForAppDidBecomeActiveNotifications { +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification; +#elif TARGET_OS_OSX + NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification; +#endif + +#if !TARGET_OS_WATCH + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidBecomeActive:) + name:notificationName + object:nil]; +#endif +} + +- (void)appDidBecomeActive:(NSNotification *)notification { + [self logCoreTelemetryIfEnabled]; +} + +- (void)logCoreTelemetryIfEnabled { + if ([self isDataCollectionDefaultEnabled]) { + [FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h new file mode 100644 index 00000000..3fc69c6c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// TODO: Remove this once Auth moves over to Core's instance registration system. +/** @class FIRAppAssociationRegistration + @brief Manages object associations as a singleton-dependent: At most one object is + registered for any given host/key pair, and the object shall be created on-the-fly when + asked for. + */ +@interface FIRAppAssociationRegistration : NSObject + +/** @fn registeredObjectWithHost:key:creationBlock: + @brief Retrieves the registered object with a particular host and key. + @param host The host object. + @param key The key to specify the registered object on the host. + @param creationBlock The block to return the object to be registered if not already. + The block is executed immediately before this method returns if it is executed at all. + It can also be executed multiple times across different method invocations if previous + execution of the block returns @c nil. + @return The registered object for the host/key pair, or @c nil if no object is registered + and @c creationBlock returns @c nil. + @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this + method again within the @c creationBlock with the same host/key pair raises an exception. + The registered object is retained by the host. + */ ++ (nullable ObjectType)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(ObjectType _Nullable (^)(void))creationBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m new file mode 100644 index 00000000..f3f812c7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m @@ -0,0 +1,47 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRAppAssociationRegistration.h" + +#import + +@implementation FIRAppAssociationRegistration + ++ (nullable id)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(id _Nullable (^)(void))creationBlock { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey); + if (!objectsByKey) { + objectsByKey = [[NSMutableDictionary alloc] init]; + objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + id obj = objectsByKey[key]; + NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey]; + if (obj) { + if ([creationBlockBeingCalled isEqual:obj]) { + [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed" + format:@"host: %@ key: %@", host, key]; + } + return obj; + } + objectsByKey[key] = creationBlockBeingCalled; + obj = creationBlock(); + objectsByKey[key] = obj; + return obj; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h new file mode 100644 index 00000000..d9475dd2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * This class provides utilities for accessing resources in bundles. + */ +@interface FIRBundleUtil : NSObject + +/** + * Finds all relevant bundles, starting with [NSBundle mainBundle]. + */ ++ (NSArray *)relevantBundles; + +/** + * Reads the options dictionary from one of the provided bundles. + * + * @param resourceName The resource name, e.g. @"GoogleService-Info". + * @param fileType The file type (extension), e.g. @"plist". + * @param bundles The bundles to expect, in priority order. See also + * +[FIRBundleUtil relevantBundles]. + */ ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles; + +/** + * Finds URL schemes defined in all relevant bundles, starting with those from + * [NSBundle mainBundle]. + */ ++ (NSArray *)relevantURLSchemes; + +/** + * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension + * suffixes). + */ ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles; + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m new file mode 100644 index 00000000..de2c2954 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m @@ -0,0 +1,79 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" + +#import + +@implementation FIRBundleUtil + ++ (NSArray *)relevantBundles { + return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ]; +} + ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles { + // Loop through all bundles to find the config dict. + for (NSBundle *bundle in bundles) { + NSString *path = [bundle pathForResource:resourceName ofType:fileType]; + // Use the first one we find. + if (path) { + return path; + } + } + return nil; +} + ++ (NSArray *)relevantURLSchemes { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (NSBundle *bundle in [[self class] relevantBundles]) { + NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]]; + } + } + return result; +} + ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { + for (NSBundle *bundle in bundles) { + if ([bundle.bundleIdentifier isEqualToString:bundleIdentifier]) { + return YES; + } + + if ([GULAppEnvironmentUtil isAppExtension]) { + // A developer could be using the same `FIROptions` for both their app and extension. Since + // extensions have a suffix added to the bundleID, we consider a matching prefix as valid. + NSString *appBundleIDFromExtension = + [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier]; + if ([appBundleIDFromExtension isEqualToString:bundleIdentifier]) { + return YES; + } + } + } + return NO; +} + ++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m new file mode 100644 index 00000000..9c1fbed3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponent.h" + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRComponent () + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock; + +@end + +@implementation FIRComponent + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; +} + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:instantiationTiming + dependencies:dependencies + creationBlock:creationBlock]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + self = [super init]; + if (self) { + _protocol = protocol; + _instantiationTiming = instantiationTiming; + _dependencies = [dependencies copy]; + _creationBlock = creationBlock; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m new file mode 100644 index 00000000..bbe88782 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m @@ -0,0 +1,214 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer () + +/// The dictionary of components that are registered for a particular app. The key is an `NSString` +/// of the protocol. +@property(nonatomic, strong) NSMutableDictionary *components; + +/// Cached instances of components that requested to be cached. +@property(nonatomic, strong) NSMutableDictionary *cachedInstances; + +/// Protocols of components that have requested to be eagerly instantiated. +@property(nonatomic, strong, nullable) NSMutableArray *eagerProtocolsToInstantiate; + +@end + +@implementation FIRComponentContainer + +// Collection of all classes that register to provide components. +static NSMutableSet *sFIRComponentRegistrants; + +#pragma mark - Public Registration + ++ (void)registerAsComponentRegistrant:(Class)klass { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sFIRComponentRegistrants = [[NSMutableSet alloc] init]; + }); + + [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants]; +} + ++ (void)registerAsComponentRegistrant:(Class)klass + inSet:(NSMutableSet *)allRegistrants { + [allRegistrants addObject:klass]; +} + +#pragma mark - Internal Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWithApp:app registrants:sFIRComponentRegistrants]; +} + +- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants { + self = [super init]; + if (self) { + _app = app; + _cachedInstances = [NSMutableDictionary dictionary]; + _components = [NSMutableDictionary dictionary]; + + [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app]; + } + return self; +} + +- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app { + // Keep track of any components that need to eagerly instantiate after all components are added. + self.eagerProtocolsToInstantiate = [[NSMutableArray alloc] init]; + + // Loop through the verified component registrants and populate the components array. + for (Class klass in classes) { + // Loop through all the components being registered and store them as appropriate. + // Classes which do not provide functionality should use a dummy FIRComponentRegistrant + // protocol. + for (FIRComponent *component in [klass componentsToRegister]) { + // Check if the component has been registered before, and error out if so. + NSString *protocolName = NSStringFromProtocol(component.protocol); + if (self.components[protocolName]) { + FIRLogError(kFIRLoggerCore, @"I-COR000029", + @"Attempted to register protocol %@, but it already has an implementation.", + protocolName); + continue; + } + + // Store the creation block for later usage. + self.components[protocolName] = component.creationBlock; + + // Queue any protocols that should be eagerly instantiated. Don't instantiate them yet + // because they could depend on other components that haven't been added to the components + // array yet. + BOOL shouldInstantiateEager = + (component.instantiationTiming == FIRInstantiationTimingAlwaysEager); + BOOL shouldInstantiateDefaultEager = + (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp && + [app isDefaultApp]); + if (shouldInstantiateEager || shouldInstantiateDefaultEager) { + [self.eagerProtocolsToInstantiate addObject:component.protocol]; + } + } + } +} + +#pragma mark - Instance Creation + +- (void)instantiateEagerComponents { + // After all components are registered, instantiate the ones that are requesting eager + // instantiation. + @synchronized(self) { + for (Protocol *protocol in self.eagerProtocolsToInstantiate) { + // Get an instance for the protocol, which will instantiate it since it couldn't have been + // cached yet. Ignore the instance coming back since we don't need it. + __unused id unusedInstance = [self instanceForProtocol:protocol]; + } + + // All eager instantiation is complete, clear the stored property now. + self.eagerProtocolsToInstantiate = nil; + } +} + +/// Instantiate an instance of a class that conforms to the specified protocol. +/// This will: +/// - Call the block to create an instance if possible, +/// - Validate that the instance returned conforms to the protocol it claims to, +/// - Cache the instance if the block requests it +/// +/// Note that this method assumes the caller already has @sychronized on self. +- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol + withBlock:(FIRComponentCreationBlock)creationBlock { + if (!creationBlock) { + return nil; + } + + // Create an instance using the creation block. + BOOL shouldCache = NO; + id instance = creationBlock(self, &shouldCache); + if (!instance) { + return nil; + } + + // An instance was created, validate that it conforms to the protocol it claims to. + NSString *protocolName = NSStringFromProtocol(protocol); + if (![instance conformsToProtocol:protocol]) { + FIRLogError(kFIRLoggerCore, @"I-COR000030", + @"An instance conforming to %@ was requested, but the instance provided does not " + @"conform to the protocol", + protocolName); + } + + // The instance is ready to be returned, but check if it should be cached first before returning. + if (shouldCache) { + self.cachedInstances[protocolName] = instance; + } + + return instance; +} + +#pragma mark - Internal Retrieval + +- (nullable id)instanceForProtocol:(Protocol *)protocol { + // Check if there is a cached instance, and return it if so. + NSString *protocolName = NSStringFromProtocol(protocol); + + id cachedInstance; + @synchronized(self) { + cachedInstance = self.cachedInstances[protocolName]; + if (!cachedInstance) { + // Use the creation block to instantiate an instance and return it. + FIRComponentCreationBlock creationBlock = self.components[protocolName]; + cachedInstance = [self instantiateInstanceForProtocol:protocol withBlock:creationBlock]; + } + } + return cachedInstance; +} + +#pragma mark - Lifecycle + +- (void)removeAllCachedInstances { + @synchronized(self) { + // Loop through the cache and notify each instance that is a maintainer to clean up after + // itself. + for (id instance in self.cachedInstances.allValues) { + if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] && + [instance respondsToSelector:@selector(appWillBeDeleted:)]) { + [instance appWillBeDeleted:self.app]; + } + } + + // Empty the cache. + [self.cachedInstances removeAllObjects]; + } +} + +- (void)removeAllComponents { + @synchronized(self) { + [self.components removeAllObjects]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h new file mode 100644 index 00000000..82356060 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainerInternal.h @@ -0,0 +1,49 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer (Private) + +/// Initializes a container for a given app. This should only be called by the app itself. +- (instancetype)initWithApp:(FIRApp *)app; + +/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the +/// protocol wasn't registered, or if the instance couldn't be instantiated for the provided app. +- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:)); + +/// Instantiates all the components that have registered as "eager" after initialization. +- (void)instantiateEagerComponents; + +/// Remove all of the cached instances stored and allow them to clean up after themselves. +- (void)removeAllCachedInstances; + +/// Removes all the components. After calling this method no new instances will be created. +- (void)removeAllComponents; + +/// Register a class to provide components for the interoperability system. The class should conform +/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects. ++ (void)registerAsComponentRegistrant:(Class)klass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m new file mode 100644 index 00000000..9051336a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentType.h" + +#import "FirebaseCore/Sources/FIRComponentContainerInternal.h" + +@implementation FIRComponentType + ++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container { + // Forward the call to the container. + return [container instanceForProtocol:protocol]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m new file mode 100644 index 00000000..83b3248c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m @@ -0,0 +1,46 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRConfigurationInternal.h" + +#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h" + +extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +@implementation FIRConfiguration + ++ (instancetype)sharedInstance { + static FIRConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance]; + } + return self; +} + +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel { + NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin, + @"Invalid logger level, %ld", (long)loggerLevel); + FIRSetLoggerLevel(loggerLevel); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h new file mode 100644 index 00000000..ee168867 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRConfiguration.h" + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m new file mode 100644 index 00000000..730dd6ef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" + +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h" + +#import "FirebaseCore/Sources/Public/FIROptions.h" + +#import "FirebaseCore/Sources/FIRDiagnosticsData.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop. +Class FIRCoreDiagnosticsImplementation; + +@implementation FIRCoreDiagnosticsConnector + ++ (void)initialize { + if (!FIRCoreDiagnosticsImplementation) { + FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics"); + if (FIRCoreDiagnosticsImplementation) { + NSAssert([FIRCoreDiagnosticsImplementation + conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)], + @"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol."); + NSAssert( + [FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)], + @"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData."); + } + } +} + ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options { + if (FIRCoreDiagnosticsImplementation) { + FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init]; + [diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey]; + [diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey]; + [diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey]; + [diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey]; + [diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey]; + [diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist) + forKey:kFIRCDUsingOptionsFromDefaultPlistKey]; + [diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey]; + [FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m new file mode 100644 index 00000000..e1e25783 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRDependency () + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +@end + +@implementation FIRDependency + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol { + return [[self alloc] initWithProtocol:protocol isRequired:YES]; +} + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + return [[self alloc] initWithProtocol:protocol isRequired:required]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + self = [super init]; + if (self) { + _protocol = protocol; + _isRequired = required; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h new file mode 100644 index 00000000..5b5ff8ad --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */ +@interface FIRDiagnosticsData : NSObject + +/** Inserts values into the diagnosticObjects dictionary if the value isn't nil. + * + * @param value The value to insert if it's not nil. + * @param key The key to associate it with. + */ +- (void)insertValue:(nullable id)value forKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m new file mode 100644 index 00000000..da9489d9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/FIRDiagnosticsData.h" + +#import "FirebaseCore/Sources/Public/FIRApp.h" + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +@implementation FIRDiagnosticsData { + /** Backing ivar for the diagnosticObjects property. */ + NSMutableDictionary *_diagnosticObjects; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _diagnosticObjects = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)insertValue:(nullable id)value forKey:(NSString *)key { + if (key) { + _diagnosticObjects[key] = value; + } +} + +#pragma mark - FIRCoreDiagnosticsData + +- (NSDictionary *)diagnosticObjects { + if (!_diagnosticObjects[kFIRCDllAppsCountKey]) { + _diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count); + } + if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) { + _diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] = + @([[FIRApp defaultApp] isDataCollectionDefaultEnabled]); + } + if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) { + _diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent]; + } + return _diagnosticObjects; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)setDiagnosticObjects:(NSDictionary *)diagnosticObjects { + NSAssert(NO, @"Please use -insertValue:forKey:"); +} +#pragma clang diagnostic pop + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m new file mode 100644 index 00000000..104eeb82 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m @@ -0,0 +1,21 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRErrors.h" + +NSString *const kFirebaseErrorDomain = @"com.firebase"; +NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config"; +NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core"; +NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf"; +NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage"; diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m new file mode 100644 index 00000000..277b0f71 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import +#import + +const static long secondsInDay = 86400; +@implementation FIRHeartbeatInfo : NSObject + +/** Updates the storage with the heartbeat information corresponding to this tag. + * @param heartbeatTag Tag which could either be sdk specific tag or the global tag. + * @return Boolean representing whether the heartbeat needs to be sent for this tag or not. + */ ++ (BOOL)updateIfNeededHeartbeatDateForTag:(NSString *)heartbeatTag { + @synchronized(self) { + NSString *const kHeartbeatStorageFile = @"HEARTBEAT_INFO_STORAGE"; + GULHeartbeatDateStorage *dataStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kHeartbeatStorageFile]; + NSDate *heartbeatTime = [dataStorage heartbeatDateForTag:heartbeatTag]; + NSDate *currentDate = [NSDate date]; + if (heartbeatTime != nil) { + NSTimeInterval secondsBetween = [currentDate timeIntervalSinceDate:heartbeatTime]; + if (secondsBetween < secondsInDay) { + return false; + } + } + return [dataStorage setHearbeatDate:currentDate forTag:heartbeatTag]; + } +} + ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag { + NSString *globalTag = @"GLOBAL"; + BOOL isSdkHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:heartbeatTag]; + BOOL isGlobalHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:globalTag]; + if (!isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Both sdk and global heartbeat not needed. + return FIRHeartbeatInfoCodeNone; + } else if (isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Only SDK heartbeat needed. + return FIRHeartbeatInfoCodeSDK; + } else if (!isSdkHeartbeatNeeded && isGlobalHeartbeatNeeded) { + // Only global heartbeat needed. + return FIRHeartbeatInfoCodeGlobal; + } else { + // Both sdk and global heartbeat are needed. + return FIRHeartbeatInfoCodeCombined; + } +} +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m new file mode 100644 index 00000000..a749cbd9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m @@ -0,0 +1,179 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +#import +#import +#import "FirebaseCore/Sources/Public/FIRLoggerLevel.h" + +#import "FirebaseCore/Sources/FIRVersion.h" + +FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]"; + +// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones! +FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]"; +FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]"; +FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]"; +FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]"; +FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]"; +FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]"; +FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]"; +FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]"; + +/// Arguments passed on launch. +NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled"; +NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled"; +NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR"; + +/// Key for the debug mode bit in NSUserDefaults. +NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode"; + +/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults` +/// will be used. +static NSUserDefaults *sFIRLoggerUserDefaults; + +static dispatch_once_t sFIRLoggerOnceToken; + +// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled +// flags used by Analytics. Users who use those flags expect Analytics to log verbosely, +// while the rest of Firebase logs at the default level. This flag is introduced to support +// that behavior. +static BOOL sFIRAnalyticsDebugMode; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void FIRLoggerInitializeASL() { + dispatch_once(&sFIRLoggerOnceToken, ^{ + // Register Firebase Version with GULLogger. + GULLoggerRegisterVersion(FIRVersionString); + + // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. + NSArray *arguments = [NSProcessInfo processInfo].arguments; + BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument]; + + // Use the standard NSUserDefaults if it hasn't been explicitly set. + if (sFIRLoggerUserDefaults == nil) { + sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults]; + } + + BOOL forceDebugMode = NO; + BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey]; + if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] || + debugMode) { // Debug mode + [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey]; + forceDebugMode = YES; + } + GULLoggerInitializeASL(); + if (overrideSTDERR) { + GULLoggerEnableSTDERR(); + } + if (forceDebugMode) { + GULLoggerForceDebug(); + } + }); +} + +__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) { + sFIRAnalyticsDebugMode = analyticsDebugMode; +} + +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) { + FIRLoggerInitializeASL(); + GULSetLoggerLevel((GULLoggerLevel)loggerLevel); +} + +#ifdef DEBUG +void FIRResetLogger() { + extern void GULResetLogger(void); + sFIRLoggerOnceToken = 0; + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + sFIRLoggerUserDefaults = nil; + GULResetLogger(); +} + +void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) { + sFIRLoggerUserDefaults = defaults; +} +#endif + +/** + * Check if the level is high enough to be loggable. + * + * Analytics can override the log level with an intentional race condition. + * Add the attribute to get a clean thread sanitizer run. + */ +__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, + BOOL analyticsComponent) { + FIRLoggerInitializeASL(); + if (sFIRAnalyticsDebugMode && analyticsComponent) { + return YES; + } + return GULIsLoggableLevel((GULLoggerLevel)loggerLevel); +} + +void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + FIRLoggerInitializeASL(); + GULLogBasic((GULLoggerLevel)level, service, + sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode, + message, args_ptr); +} + +/** + * Generates the logging functions using macros. + * + * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed. + * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed. + */ +#define FIR_LOGGING_FUNCTION(level) \ + void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +FIR_LOGGING_FUNCTION(Error) +FIR_LOGGING_FUNCTION(Warning) +FIR_LOGGING_FUNCTION(Notice) +FIR_LOGGING_FUNCTION(Info) +FIR_LOGGING_FUNCTION(Debug) + +#undef FIR_MAKE_LOGGER + +#pragma mark - FIRLoggerWrapper + +@implementation FIRLoggerWrapper + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + FIRLogBasic(level, service, messageCode, message, args); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m new file mode 100644 index 00000000..d1853309 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m @@ -0,0 +1,490 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Keys for the strings in the plist file. +NSString *const kFIRAPIKey = @"API_KEY"; +NSString *const kFIRTrackingID = @"TRACKING_ID"; +NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID"; +NSString *const kFIRClientID = @"CLIENT_ID"; +NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID"; +NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID"; +NSString *const kFIRDatabaseURL = @"DATABASE_URL"; +NSString *const kFIRStorageBucket = @"STORAGE_BUCKET"; +// The key to locate the expected bundle identifier in the plist file. +NSString *const kFIRBundleID = @"BUNDLE_ID"; +// The key to locate the project identifier in the plist file. +NSString *const kFIRProjectID = @"PROJECT_ID"; + +NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED"; + +NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED"; +NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED"; + +// Library version ID formatted like: +// @"5" // Major version (one or more digits) +// @"04" // Minor version (exactly 2 digits) +// @"01" // Build number (exactly 2 digits) +// @"000"; // Fixed "000" +NSString *kFIRLibraryVersionID; + +// Plist file name. +NSString *const kServiceInfoFileName = @"GoogleService-Info"; +// Plist file type. +NSString *const kServiceInfoFileType = @"plist"; + +// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp. +NSString *const kFIRExceptionBadModification = + @"Attempted to modify options after it's set on FIRApp. Please modify all properties before " + @"initializing FIRApp."; + +@interface FIROptions () + +/** + * This property maintains the actual configuration key-value pairs. + */ +@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary; + +/** + * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary. + * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the main plist override values from the GoogleService-Info.plist. + */ +@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary; + +/** + * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the infoDictionary override values from the GoogleService-Info.plist. + */ +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary; + +/** + * Throw exception if editing is locked when attempting to modify an option. + */ +- (void)checkEditingLocked; + +@end + +@implementation FIROptions { + /// Backing variable for self.analyticsOptionsDictionary. + NSDictionary *_analyticsOptionsDictionary; +} + +static FIROptions *sDefaultOptions = nil; +static NSDictionary *sDefaultOptionsDictionary = nil; + +#pragma mark - Public only for internal class methods + ++ (FIROptions *)defaultOptions { + if (sDefaultOptions != nil) { + return sDefaultOptions; + } + + NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary]; + if (defaultOptionsDictionary == nil) { + return nil; + } + + sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary]; + return sDefaultOptions; +} + +#pragma mark - Private class methods + ++ (NSDictionary *)defaultOptionsDictionary { + if (sDefaultOptionsDictionary != nil) { + return sDefaultOptionsDictionary; + } + NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName]; + if (plistFilePath == nil) { + return nil; + } + sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath]; + if (sDefaultOptionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000011", + @"The configuration file is not a dictionary: " + @"'%@.%@'.", + kServiceInfoFileName, kServiceInfoFileType); + } + return sDefaultOptionsDictionary; +} + +// Returns the path of the plist file with a given file name. ++ (NSString *)plistFilePathWithName:(NSString *)fileName { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *plistFilePath = + [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName + andFileType:kServiceInfoFileType + inBundles:bundles]; + if (plistFilePath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.", + fileName, kServiceInfoFileType); + } + return plistFilePath; +} + ++ (void)resetDefaultOptions { + sDefaultOptions = nil; + sDefaultOptionsDictionary = nil; +} + +#pragma mark - Private instance methods + +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary { + self = [super init]; + if (self) { + _optionsDictionary = [optionsDictionary mutableCopy]; + _usingOptionsFromDefaultPlist = YES; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + FIROptions *newOptions = [[[self class] allocWithZone:zone] init]; + if (newOptions) { + newOptions.optionsDictionary = self.optionsDictionary; + newOptions.deepLinkURLScheme = self.deepLinkURLScheme; + newOptions.appGroupID = self.appGroupID; + newOptions.editingLocked = self.isEditingLocked; + newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist; + } + return newOptions; +} + +#pragma mark - Public instance methods + +- (instancetype)initWithContentsOfFile:(NSString *)plistPath { + self = [super init]; + if (self) { + if (plistPath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil."); + return nil; + } + _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy]; + if (_optionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000014", + @"The configuration file at %@ does not exist or " + @"is not a well-formed plist file.", + plistPath); + return nil; + } + // TODO: Do we want to validate the dictionary here? It says we do that already in + // the public header. + } + return self; +} + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary]; + [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID]; + [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID]; + [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID]; + self.optionsDictionary = mutableOptionsDict; + } + return self; +} + +- (NSString *)APIKey { + return self.optionsDictionary[kFIRAPIKey]; +} + +- (void)checkEditingLocked { + if (self.isEditingLocked) { + [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification]; + } +} + +- (void)setAPIKey:(NSString *)APIKey { + [self checkEditingLocked]; + _optionsDictionary[kFIRAPIKey] = [APIKey copy]; +} + +- (NSString *)clientID { + return self.optionsDictionary[kFIRClientID]; +} + +- (void)setClientID:(NSString *)clientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRClientID] = [clientID copy]; +} + +- (NSString *)trackingID { + return self.optionsDictionary[kFIRTrackingID]; +} + +- (void)setTrackingID:(NSString *)trackingID { + [self checkEditingLocked]; + _optionsDictionary[kFIRTrackingID] = [trackingID copy]; +} + +- (NSString *)GCMSenderID { + return self.optionsDictionary[kFIRGCMSenderID]; +} + +- (void)setGCMSenderID:(NSString *)GCMSenderID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy]; +} + +- (NSString *)projectID { + return self.optionsDictionary[kFIRProjectID]; +} + +- (void)setProjectID:(NSString *)projectID { + [self checkEditingLocked]; + _optionsDictionary[kFIRProjectID] = [projectID copy]; +} + +- (NSString *)androidClientID { + return self.optionsDictionary[kFIRAndroidClientID]; +} + +- (void)setAndroidClientID:(NSString *)androidClientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy]; +} + +- (NSString *)googleAppID { + return self.optionsDictionary[kFIRGoogleAppID]; +} + +- (void)setGoogleAppID:(NSString *)googleAppID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy]; +} + +- (NSString *)libraryVersionID { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The unit tests are set up to catch anything that does not properly convert. + NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString]; + NSArray *components = [version componentsSeparatedByString:@"."]; + NSString *major = [components objectAtIndex:0]; + NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]]; + NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]]; + kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch]; + }); + return kFIRLibraryVersionID; +} + +- (void)setLibraryVersionID:(NSString *)libraryVersionID { + _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy]; +} + +- (NSString *)databaseURL { + return self.optionsDictionary[kFIRDatabaseURL]; +} + +- (void)setDatabaseURL:(NSString *)databaseURL { + [self checkEditingLocked]; + + _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy]; +} + +- (NSString *)storageBucket { + return self.optionsDictionary[kFIRStorageBucket]; +} + +- (void)setStorageBucket:(NSString *)storageBucket { + [self checkEditingLocked]; + _optionsDictionary[kFIRStorageBucket] = [storageBucket copy]; +} + +- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme { + [self checkEditingLocked]; + _deepLinkURLScheme = [deepLinkURLScheme copy]; +} + +- (NSString *)bundleID { + return self.optionsDictionary[kFIRBundleID]; +} + +- (void)setBundleID:(NSString *)bundleID { + [self checkEditingLocked]; + _optionsDictionary[kFIRBundleID] = [bundleID copy]; +} + +- (void)setAppGroupID:(NSString *)appGroupID { + [self checkEditingLocked]; + _appGroupID = [appGroupID copy]; +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + if (!object || ![object isKindOfClass:[FIROptions class]]) { + return NO; + } + + return [self isEqualToOptions:(FIROptions *)object]; +} + +- (BOOL)isEqualToOptions:(FIROptions *)options { + // Skip any non-FIROptions classes. + if (![options isKindOfClass:[FIROptions class]]) { + return NO; + } + + // Check the internal dictionary and custom properties for differences. + if (![options.optionsDictionary isEqualToDictionary:self.optionsDictionary]) { + return NO; + } + + // Validate extra properties not contained in the dictionary. Only validate it if one of the + // objects has the property set. + if ((options.deepLinkURLScheme != nil || self.deepLinkURLScheme != nil) && + ![options.deepLinkURLScheme isEqualToString:self.deepLinkURLScheme]) { + return NO; + } + + if ((options.appGroupID != nil || self.appGroupID != nil) && + ![options.appGroupID isEqualToString:self.appGroupID]) { + return NO; + } + + // Validate the Analytics options haven't changed with the Info.plist. + if (![options.analyticsOptionsDictionary isEqualToDictionary:self.analyticsOptionsDictionary]) { + return NO; + } + + // We don't care about the `editingLocked` or `usingOptionsFromDefaultPlist` properties since + // those relate to lifecycle and construction, we only care if the contents of the options + // themselves are equal. + return YES; +} + +- (NSUInteger)hash { + // This is strongly recommended for any object that implements a custom `isEqual:` method to + // ensure that dictionary and set behavior matches other `isEqual:` checks. + // Note: `self.analyticsOptionsDictionary` was left out here since it solely relies on the + // contents of the main bundle's `Info.plist`. We should avoid reading that file and the contents + // should be identical. + return self.optionsDictionary.hash ^ self.deepLinkURLScheme.hash ^ self.appGroupID.hash; +} + +#pragma mark - Internal instance methods + +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary { + if (_analyticsOptionsDictionary == nil) { + NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init]; + NSArray *measurementKeys = @[ + kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled, + kFIRIsAnalyticsCollectionDeactivated + ]; + for (NSString *key in measurementKeys) { + id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil; + if (!value) { + continue; + } + tempAnalyticsOptions[key] = value; + } + _analyticsOptionsDictionary = tempAnalyticsOptions; + } + return _analyticsOptionsDictionary; +} + +- (NSDictionary *)analyticsOptionsDictionary { + return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary]; +} + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still + * be supported. + */ +- (BOOL)isMeasurementEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (value == nil) { + // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have + // to check if it's the default app. The FIROptions instance can't be modified after + // `+configure` is called, so it's not a good place to copy it either in case the flag is + // changed at runtime. + + // If no values are set for Analytics, fall back to the global collection switch in FIRApp. + // Analytics only supports the default FIRApp, so check that first. + if (![FIRApp isDefaultAppConfigured]) { + return NO; + } + + // Fall back to the default app's collection switch when the key is not in the dictionary. + return [FIRApp defaultApp].isDataCollectionDefaultEnabled; + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionExplicitlySet { + // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication + // that the developer wants FirebaseAnalytics enabled so continue checking. + if (self.isAnalyticsCollectionDeactivated) { + return YES; + } + + // Check if the current Analytics flag is set. + id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // Check if the old measurement flag is set. + id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // No flags are set to explicitly enable or disable FirebaseAnalytics. + return NO; +} + +- (BOOL)isAnalyticsCollectionEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (value == nil) { + return self.isMeasurementEnabled; // Fall back to older plist flag. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionDeactivated { + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated]; + if (value == nil) { + return NO; // Analytics Collection is not deactivated when the key is not in the dictionary. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsEnabled { + return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue]; +} + +- (BOOL)isSignInEnabled { + return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h new file mode 100644 index 00000000..226efb1a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The version of the Firebase SDK. */ +FOUNDATION_EXPORT const char *const FIRVersionString; + +/** The version of the FirebaseCore Component. */ +FOUNDATION_EXPORT const char *const FIRCoreVersionString; diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m new file mode 100644 index 00000000..ec0f6ba6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_VERSION +#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation" +#endif + +#ifndef FIRCore_VERSION +#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation" +#endif + +// The following two macros supply the incantation so that the C +// preprocessor does not try to parse the version as a floating +// point number. See +// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/ +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION); +const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION); diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h new file mode 100644 index 00000000..f5578c6a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h @@ -0,0 +1,127 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** A block that takes a BOOL and has no return value. */ +typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback); + +/** + * The entry point of Firebase SDKs. + * + * Initialize and configure FIRApp using +[FIRApp configure] + * or other customized ways as shown below. + * + * The logging system has two modes: default mode and debug mode. In default mode, only logs with + * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent + * to device. The log levels that Firebase uses are consistent with the ASL log levels. + * + * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this + * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled, + * further executions of the application will also be in debug mode. In order to return to default + * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled. + * + * It is also possible to change the default logging level in code by calling setLoggerLevel: on + * the FIRConfiguration interface. + */ +NS_SWIFT_NAME(FirebaseApp) +@interface FIRApp : NSObject + +/** + * Configures a default Firebase app. Raises an exception if any configuration step fails. The + * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched + * and before using Firebase services. This method should be called from the main thread and + * contains synchronous file I/O (reading GoogleService-Info.plist from disk). + */ ++ (void)configure; + +/** + * Configures the default Firebase app with the provided options. The default app is named + * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method should be + * called from the main thread. + * + * @param options The Firebase application options used to configure the service. + */ ++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:)); + +/** + * Configures a Firebase app with the given name and options. Raises an exception if any + * configuration step fails. This method should be called from the main thread. + * + * @param name The application's name given by the developer. The name should should only contain + Letters, Numbers and Underscore. + * @param options The Firebase application options used to configure the services. + */ +// clang-format off ++ (void)configureWithName:(NSString *)name + options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:)); +// clang-format on + +/** + * Returns the default app, or nil if the default app does not exist. + */ ++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app()); + +/** + * Returns a previously created FIRApp instance with the given name, or nil if no such app exists. + * This method is thread safe. + */ ++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:)); + +/** + * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This + * method is thread safe. + */ +@property(class, readonly, nullable) NSDictionary *allApps; + +/** + * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for + * future use. This method is thread safe. + */ +- (void)deleteApp:(FIRAppVoidBoolCallback)completion; + +/** + * FIRApp instances should not be initialized directly. Call +[FIRApp configure], + * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Gets the name of this app. + */ +@property(nonatomic, copy, readonly) NSString *name; + +/** + * Gets a copy of the options for this app. These are non-modifiable. + */ +@property(nonatomic, copy, readonly) FIROptions *options; + +/** + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value + * is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled) + BOOL dataCollectionDefaultEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h new file mode 100644 index 00000000..2b8e678c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRLoggerLevel.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This interface provides global level properties that the developer can tweak. + */ +NS_SWIFT_NAME(FirebaseConfiguration) +@interface FIRConfiguration : NSObject + +/** Returns the shared configuration object. */ +@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared); + +/** + * Sets the logging level for internal Firebase logging. Firebase will only log messages + * that are logged at or below loggerLevel. The messages are logged both to the Xcode + * console and to the device's log. Note that if an app is running from AppStore, it will + * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose) + * setting. + * + * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice. + */ +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h new file mode 100644 index 00000000..dca3aa0b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note that importing GULLoggerLevel.h will lead to a non-modular header +// import error. + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, FIRLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + FIRLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + FIRLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + FIRLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + FIRLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + FIRLoggerLevelDebug = 7, + /** Minimum log level. */ + FIRLoggerLevelMin = FIRLoggerLevelError, + /** Maximum log level. */ + FIRLoggerLevelMax = FIRLoggerLevelDebug +} NS_SWIFT_NAME(FirebaseLoggerLevel); diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h new file mode 100644 index 00000000..67fbe5ba --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class provides constant fields of Google APIs. + */ +NS_SWIFT_NAME(FirebaseOptions) +@interface FIROptions : NSObject + +/** + * Returns the default options. The first time this is called it synchronously reads + * GoogleService-Info.plist from disk. + */ ++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions()); + +/** + * An iOS API key used for authenticating requests from your app, e.g. + * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers. + */ +@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey); + +/** + * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set + * manually or in a plist. + */ +@property(nonatomic, copy) NSString *bundleID; + +/** + * The OAuth2 client ID for iOS application used to authenticate Google users, for example + * @"12345.apps.googleusercontent.com", used for signing in with Google. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** + * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics. + */ +@property(nonatomic, copy, nullable) NSString *trackingID; + +/** + * The Project Number from the Google Developer's console, for example @"012345678901", used to + * configure Google Cloud Messaging. + */ +@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID); + +/** + * The Project ID from the Firebase console, for example @"abc-xyz-123". + */ +@property(nonatomic, copy, nullable) NSString *projectID; + +/** + * The Android client ID used in Google AppInvite when an iOS app has its Android version, for + * example @"12345.apps.googleusercontent.com". + */ +@property(nonatomic, copy, nullable) NSString *androidClientID; + +/** + * The Google App ID that is used to uniquely identify an instance of an app. + */ +@property(nonatomic, copy) NSString *googleAppID; + +/** + * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com". + */ +@property(nonatomic, copy, nullable) NSString *databaseURL; + +/** + * The URL scheme used to set up Durable Deep Link service. + */ +@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme; + +/** + * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com". + */ +@property(nonatomic, copy, nullable) NSString *storageBucket; + +/** + * The App Group identifier to share data between the application and the application extensions. + * The App Group must be configured in the application and on the Apple Developer Portal. Default + * value `nil`. + */ +@property(nonatomic, copy, nullable) NSString *appGroupID; + +/** + * Initializes a customized instance of FIROptions from the file at the given plist file path. This + * will read the file synchronously from disk. + * For example, + * NSString *filePath = + * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + * Returns nil if the plist file does not exist or is invalid. + */ +- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath; + +/** + * Initializes a customized instance of FIROptions with required fields. Use the mutable properties + * to modify fields for configuring specific services. + */ +// clang-format off +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + GCMSenderID:(NSString *)GCMSenderID + NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)); +// clang-format on + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h new file mode 100644 index 00000000..95119aed --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" diff --git a/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h new file mode 100644 index 00000000..69c40721 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkNameKey @"FIRCDSdkNameKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey" + +/** If present, is an NSString. */ +#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey" + +/** If present, is an NSString. */ +#define kFIRCDBundleIDKey @"FIRCDBundleID" + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey" + +/** If present, is an NSString. */ +#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey" + +/** If present, is an NSString. */ +#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey" + +/** Defines the interface of a data object needed to log diagnostics data. */ +@protocol FIRCoreDiagnosticsData + +@required + +/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */ +@property(nonatomic) NSDictionary *diagnosticObjects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 00000000..2b0eb710 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCore/LICENSE b/MyExperiences copy/Pods/FirebaseCore/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseCore/README.md b/MyExperiences copy/Pods/FirebaseCore/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCore/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m new file mode 100644 index 00000000..2db7db83 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m @@ -0,0 +1,647 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#include + +#import +#import +#import +#import + +#import +#import +#import + +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h" +#import "Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h" + +#import +#import +#import + +#import "FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h" + +/** The logger service string to use when printing to the console. */ +static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]"; + +#ifdef FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = YES; +#else // FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = NO; +#endif // FIREBASE_BUILD_ZIP_FILE + +#ifdef FIREBASE_BUILD_CARTHAGE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE +#elif FIREBASE_BUILD_ZIP_FILE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE +#else +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS +#endif + +static NSString *const kFIRServiceMLVisionOnDeviceAutoML = @"MLVisionOnDeviceAutoML"; +static NSString *const kFIRServiceMLVisionOnDeviceFace = @"MLVisionOnDeviceFace"; +static NSString *const kFIRServiceMLVisionOnDeviceBarcode = @"MLVisionOnDeviceBarcode"; +static NSString *const kFIRServiceMLVisionOnDeviceText = @"MLVisionOnDeviceText"; +static NSString *const kFIRServiceMLVisionOnDeviceLabel = @"MLVisionOnDeviceLabel"; +static NSString *const kFIRServiceMLVisionOnDeviceObjectDetection = + @"MLVisionOnDeviceObjectDetection"; +static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter"; + +static NSString *const kFIRServiceAdMob = @"AdMob"; +static NSString *const kFIRServiceAuth = @"Auth"; +static NSString *const kFIRServiceAuthUI = @"AuthUI"; +static NSString *const kFIRServiceCrash = @"Crash"; +static NSString *const kFIRServiceDatabase = @"Database"; +static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks"; +static NSString *const kFIRServiceFirestore = @"Firestore"; +static NSString *const kFIRServiceFunctions = @"Functions"; +static NSString *const kFIRServiceIAM = @"InAppMessaging"; +static NSString *const kFIRServiceInstanceID = @"InstanceID"; +static NSString *const kFIRServiceInvites = @"Invites"; +static NSString *const kFIRServiceMessaging = @"Messaging"; +static NSString *const kFIRServiceMeasurement = @"Measurement"; +static NSString *const kFIRServicePerformance = @"Performance"; +static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig"; +static NSString *const kFIRServiceStorage = @"Storage"; +static NSString *const kGGLServiceAnalytics = @"Analytics"; +static NSString *const kGGLServiceSignIn = @"SignIn"; +static NSString *const kFIRAppDiagnosticsConfigurationTypeKey = + @"FIRAppDiagnosticsConfigurationTypeKey"; +static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey"; +static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey"; +static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey"; +static NSString *const kFIRCoreDiagnosticsHeartbeatTag = @"FIRCoreDiagnostics"; + +/** + * The file name to the recent heartbeat date. + */ +NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE"; + +/** + * @note This should implement the GDTCOREventDataObject protocol, but can't because of + * weak-linking. + */ +@interface FIRCoreDiagnosticsLog : NSObject + +/** The config that will be converted to proto bytes. */ +@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config; + +@end + +@implementation FIRCoreDiagnosticsLog + +- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config { + self = [super init]; + if (self) { + _config = config; + } + return self; +} + +// Provided and required by the GDTCOREventDataObject protocol. +- (NSData *)transportBytes { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + CFDataSetLength(dataRef, bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + CFDataSetLength(dataRef, ostream.bytes_written); + + return CFBridgingRelease(dataRef); +} + +- (void)dealloc { + pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config); +} + +@end + +NS_ASSUME_NONNULL_BEGIN + +/** This class produces a protobuf containing diagnostics and usage data to be logged. */ +@interface FIRCoreDiagnostics : NSObject + +/** The queue on which all diagnostics collection will occur. */ +@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue; + +/** The transport object used to send data. */ +@property(nonatomic, readonly) GDTCORTransport *transport; + +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) GULHeartbeatDateStorage *heartbeatDateStorage; + +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRCoreDiagnostics + ++ (instancetype)sharedInstance { + static FIRCoreDiagnostics *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRCoreDiagnostics alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"137" + transformers:nil + target:kGDTCORTargetFLL]; + + GULHeartbeatDateStorage *dateStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kFIRCoreDiagnosticsHeartbeatDateFileName]; + + return [self initWithTransport:transport heartbeatDateStorage:dateStorage]; +} + +/** Initializer for unit tests. + * + * @param transport A `GDTCORTransport` instance which that be used to send event. + * @param heartbeatDateStorage An instanse of date storage to track heartbeat sending. + * @return Returns the initialized `FIRCoreDiagnostics` instance. + */ +- (instancetype)initWithTransport:(GDTCORTransport *)transport + heartbeatDateStorage:(GULHeartbeatDateStorage *)heartbeatDateStorage { + self = [super init]; + if (self) { + _diagnosticsQueue = + dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL); + _transport = transport; + _heartbeatDateStorage = heartbeatDateStorage; + } + return self; +} + +#pragma mark - Metadata helpers + +/** Returns the model of iOS device. Sample platform strings are @"iPhone7,1" for iPhone 6 Plus, + * @"iPhone7,2" for iPhone 6, etc. Refer to the Hardware strings at + * https://en.wikipedia.org/wiki/List_of_iOS_devices + * + * @return The device model as an NSString. + */ ++ (NSString *)deviceModel { + static NSString *deviceModel = nil; + if (deviceModel == nil) { + struct utsname systemInfo; + uname(&systemInfo); + deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + } + return deviceModel; +} + +#pragma mark - nanopb helper functions + +/** Callocs a pb_bytes_array and copies the given NSString's bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param string The string to encode as pb_bytes. + */ +pb_bytes_array_t *FIREncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return FIREncodeData(stringBytes); +} + +/** Callocs a pb_bytes_array and copies the given NSData bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param data The data to copy into the new bytes array. + */ +pb_bytes_array_t *FIREncodeData(NSData *data) { + pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + if (pbBytesArray != NULL) { + [data getBytes:pbBytesArray->bytes length:data.length]; + pbBytesArray->size = (pb_size_t)data.length; + } + return pbBytesArray; +} + +/** Maps a service string to the representative nanopb enum. + * + * @param serviceString The SDK service string to convert. + * @return The representative nanopb enum. + */ +logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum( + NSString *serviceString) { + static NSDictionary *serviceStringToTypeEnum; + if (serviceStringToTypeEnum == nil) { + serviceStringToTypeEnum = @{ + kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB), + kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING), + kFIRServiceMeasurement : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT), + kFIRServiceRemoteConfig : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG), + kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE), + kFIRServiceDynamicLinks : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS), + kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH), + kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI), + kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE), + kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS), + kFIRServicePerformance : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE), + kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE), + kFIRServiceMLVisionOnDeviceAutoML : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML), + kFIRServiceMLVisionOnDeviceFace : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE), + kFIRServiceMLVisionOnDeviceBarcode : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE), + kFIRServiceMLVisionOnDeviceText : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT), + kFIRServiceMLVisionOnDeviceLabel : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL), + kFIRServiceMLVisionOnDeviceObjectDetection : @( + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION), + kFIRServiceMLModelInterpreter : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER), + kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS), + kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN), + kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING), + }; + } + if (serviceStringToTypeEnum[serviceString] != nil) { + return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue; + } + return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE; +} + +#pragma mark - Proto population functions + +/** Populates the given proto with data related to an SDK logDiagnostics call from the + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey]; + if (configurationType != nil) { + switch (configurationType.integerValue) { + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE; + config->has_configuration_type = 1; + break; + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK; + config->has_configuration_type = 1; + break; + default: + break; + } + } + + NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey]; + if (sdkName) { + config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName); + config->has_sdk_name = 1; + } + + NSString *version = diagnosticObjects[kFIRCDSdkVersionKey]; + if (version) { + config->sdk_version = FIREncodeString(version); + } +} + +/** Populates the given proto with data from the calling FIRApp using the given + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE; + config->has_pod_name = 1; + + if (!diagnosticObjects[kFIRCDllAppsCountKey]) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"App count is a required value in the data dict."); + } + config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue]; + config->has_app_count = 1; + + NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey]; + if (googleAppID.length) { + config->app_id = FIREncodeString(googleAppID); + } + + NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey]; + if (bundleID.length) { + config->bundle_id = FIREncodeString(bundleID); + } + + NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey]; + if (firebaseUserAgent.length) { + config->platform_info = FIREncodeString(firebaseUserAgent); + } + + NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey]; + if (usingOptionsFromDefaultPlist != nil) { + config->use_default_app = [usingOptionsFromDefaultPlist boolValue]; + config->has_use_default_app = 1; + } + + NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey]; + if (libraryVersionID) { + config->icore_version = FIREncodeString(libraryVersionID); + } + + NSString *deviceModel = [FIRCoreDiagnostics deviceModel]; + if (deviceModel.length) { + config->device_model = FIREncodeString(deviceModel); + } + + NSString *osVersion = [GULAppEnvironmentUtil systemVersion]; + if (osVersion.length) { + config->os_version = FIREncodeString(osVersion); + } + + config->using_zip_file = kUsingZipFile; + config->has_using_zip_file = 1; + config->deployment_type = kDeploymentType; + config->has_deployment_type = 1; + config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore]; + config->has_deployed_in_app_store = 1; +} + +/** Populates the given proto with installed services data. + * + * @param config The proto to populate + */ +void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSMutableArray *sdkServiceInstalledArray = [NSMutableArray array]; + + // AdMob + if (NSClassFromString(@"GADBannerView") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))]; + } + // CloudMessaging + if (NSClassFromString(@"FIRMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))]; + } + // RemoteConfig + if (NSClassFromString(@"FIRRemoteConfig") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))]; + } + // Measurement/Analtyics + if (NSClassFromString(@"FIRAnalytics") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))]; + } + // ML Vision On Device AutoML. + if (NSClassFromString(@"FIRVisionOnDeviceAutoMLImageLabelerOptions") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceAutoML))]; + } + // ML Vision On Device Face. + if (NSClassFromString(@"FIRVisionFaceDetector") != nil && + NSClassFromString(@"GMVFaceDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceFace))]; + } + // ML Vision On Device Barcode. + if (NSClassFromString(@"FIRVisionBarcodeDetector") != nil && + NSClassFromString(@"GMVBarcodeDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceBarcode))]; + } + // ML Vision On Device Text. + if (NSClassFromString(@"FIRVisionTextDetector") != nil && + NSClassFromString(@"GMVTextDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceText))]; + } + // ML Vision On Device Image Label. + if (NSClassFromString(@"FIRVisionLabelDetector") != nil && + NSClassFromString(@"GMVLabelDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceLabel))]; + } + // ML Vision On Device Object. + if (NSClassFromString(@"FIRVisionObjectDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceObjectDetection))]; + } + // ML Model Interpreter + if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))]; + } + // Database + if (NSClassFromString(@"FIRDatabase") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))]; + } + // DynamicDeepLink + if (NSClassFromString(@"FIRDynamicLinks") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))]; + } + // Auth + if (NSClassFromString(@"FIRAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))]; + } + // AuthUI + if (NSClassFromString(@"FUIAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))]; + } + // Firestore + if (NSClassFromString(@"FIRFirestore") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))]; + } + // Functions + if (NSClassFromString(@"FIRFunctions") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))]; + } + // Performance + if (NSClassFromString(@"FIRPerformance") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))]; + } + // Storage + if (NSClassFromString(@"FIRStorage") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))]; + } + // SignIn via Google pod + if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))]; + } + // Analytics via Google pod + if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))]; + } + + // In-App Messaging + if (NSClassFromString(@"FIRInAppMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))]; + } + + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled = + calloc(sdkServiceInstalledArray.count, + sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)); + if (servicesInstalled == NULL) { + return; + } + for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) { + NSNumber *typeEnum = sdkServiceInstalledArray[i]; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType = + (int32_t)typeEnum.integerValue; + servicesInstalled[i] = serviceType; + } + + config->sdk_service_installed = servicesInstalled; + config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count; +} + +/** Populates the proto with the number of linked frameworks. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithNumberOfLinkedFrameworks( + logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + int numFrameworks = -1; // Subtract the app binary itself. + unsigned int numImages; + const char **imageNames = objc_copyImageNames(&numImages); + for (unsigned int i = 0; i < numImages; i++) { + NSString *imageName = [NSString stringWithUTF8String:imageNames[i]]; + if ([imageName rangeOfString:@"System/Library"].length != 0 // Apple .frameworks + || [imageName rangeOfString:@"Developer/Library"].length != 0 // Xcode debug .frameworks + || [imageName rangeOfString:@"usr/lib"].length != 0) { // Public .dylibs + continue; + } + numFrameworks++; + } + free(imageNames); + config->dynamic_framework_count = numFrameworks; + config->has_dynamic_framework_count = 1; +} + +/** Populates the proto with Info.plist values. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + + NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @""; + NSString *sdkVersion = info[@"DTSDKBuild"] ?: @""; + NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion]; + config->apple_framework_version = FIREncodeString(combinedVersions); + + NSString *minVersion = info[@"MinimumOSVersion"]; + if (minVersion) { + config->min_supported_ios_version = FIREncodeString(minVersion); + } + + // Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and + // report it. It's enabled by default. + NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"]; + BOOL appDelegateSwizzled = YES; + if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) { + appDelegateSwizzled = [appDelegateSwizzledNum boolValue]; + } + config->swizzling_enabled = appDelegateSwizzled; + config->has_swizzling_enabled = 1; +} + +#pragma mark - FIRCoreDiagnosticsInterop + ++ (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance]; + [diagnostics sendDiagnosticsData:diagnosticsData]; +} + +- (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + dispatch_async(self.diagnosticsQueue, ^{ + NSDictionary *diagnosticObjects = diagnosticsData.diagnosticObjects; + NSNumber *isDataCollectionDefaultEnabled = + diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]; + if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) { + return; + } + + // Create the proto. + logs_proto_mobilesdk_ios_ICoreConfiguration icore_config = + logs_proto_mobilesdk_ios_ICoreConfiguration_init_default; + + icore_config.using_gdt = 1; + icore_config.has_using_gdt = 1; + + // Populate the proto with information. + FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects); + FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects); + FIRPopulateProtoWithInstalledServices(&icore_config); + FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config); + FIRPopulateProtoWithInfoPlistValues(&icore_config); + [self setHeartbeatFlagIfNeededToConfig:&icore_config]; + + // This log object is capable of converting the proto to bytes. + FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config]; + + // Send the log as a telemetry event. + GDTCOREvent *event = [self.transport eventForTransport]; + event.dataObject = (id)log; + [self.transport sendTelemetryEvent:event]; + }); +} + +#pragma mark - Heartbeat + +- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config { + // Check if need to send a heartbeat. + NSDate *currentDate = [NSDate date]; + NSDate *lastCheckin = + [self.heartbeatDateStorage heartbeatDateForTag:kFIRCoreDiagnosticsHeartbeatTag]; + if (lastCheckin) { + // Ensure the previous checkin was on a different date in the past. + if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) { + return; + } + } + + // Update heartbeat sent date. + [self.heartbeatDateStorage setHearbeatDate:currentDate forTag:kFIRCoreDiagnosticsHeartbeatTag]; + // Set the flag. + config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE; + config->has_sdk_name = 1; +} + +- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 { + return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] || + [date1 compare:date2] == NSOrderedAscending; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c new file mode 100644 index 00000000..0bdb27e2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.5 */ + +#include "firebasecore.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0), + PB_FIELD( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, configuration_type, 0), + PB_FIELD( 9, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0), + PB_FIELD( 10, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0), + PB_FIELD( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, app_id, 0), + PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, bundle_id, 0), + PB_FIELD( 18, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0), + PB_FIELD( 19, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0), + PB_FIELD( 20, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0), + PB_FIELD( 21, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0), + PB_FIELD( 22, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0), + PB_FIELD( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, os_version, 0), + PB_FIELD( 25, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0), + PB_FIELD( 26, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0), + PB_FIELD( 27, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0), + PB_FIELD( 28, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0), + PB_FIELD( 29, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0), + PB_FIELD( 30, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0), + PB_FIELD( 31, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0), + PB_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, platform_info, 0), + PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, swizzling_enabled, 0), + PB_LAST_FIELD +}; + + + + + + + +/* @@protoc_insertion_point(eof) */ diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h new file mode 100644 index 00000000..59d1b3b0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h @@ -0,0 +1,193 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.5 */ + +#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType { + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3 +} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName { + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType { + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4 +} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1)) + +/* Struct definitions */ +typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration { + bool has_configuration_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type; + pb_size_t sdk_service_installed_count; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed; + pb_bytes_array_t *device_model; + pb_bytes_array_t *app_id; + pb_bytes_array_t *bundle_id; + bool has_pod_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name; + pb_bytes_array_t *icore_version; + pb_bytes_array_t *sdk_version; + bool has_sdk_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name; + bool has_app_count; + int32_t app_count; + pb_bytes_array_t *os_version; + pb_bytes_array_t *min_supported_ios_version; + bool has_use_default_app; + bool use_default_app; + bool has_deployed_in_app_store; + bool deployed_in_app_store; + bool has_dynamic_framework_count; + int32_t dynamic_framework_count; + pb_bytes_array_t *apple_framework_version; + bool has_using_zip_file; + bool using_zip_file; + bool has_deployment_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type; + pb_bytes_array_t *platform_info; + bool has_swizzling_enabled; + bool swizzling_enabled; + bool has_using_gdt; + bool using_gdt; +/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */ +} logs_proto_mobilesdk_ios_ICoreConfiguration; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22]; + +/* Maximum encoded size of messages (where known) */ +/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define FIREBASECORE_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h new file mode 100644 index 00000000..69c40721 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkNameKey @"FIRCDSdkNameKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey" + +/** If present, is an NSString. */ +#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey" + +/** If present, is an NSString. */ +#define kFIRCDBundleIDKey @"FIRCDBundleID" + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey" + +/** If present, is an NSString. */ +#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey" + +/** If present, is an NSString. */ +#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey" + +/** Defines the interface of a data object needed to log diagnostics data. */ +@protocol FIRCoreDiagnosticsData + +@required + +/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */ +@property(nonatomic) NSDictionary *diagnosticObjects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 00000000..2b0eb710 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/LICENSE b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseCoreDiagnostics/README.md b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseCoreDiagnostics/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m new file mode 100644 index 00000000..c1d48ecd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m @@ -0,0 +1,105 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FChildrenNode.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseReference.h" +#import "FTransformedEnumerator.h" +#import "FValidation.h" + +@interface FIRDataSnapshot () +@property(nonatomic, strong) FIRDatabaseReference *ref; +@end + +@implementation FIRDataSnapshot + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node { + self = [super init]; + if (self != nil) { + self->_ref = ref; + self->_node = node; + } + return self; +} + +- (id)value { + return [self.node.node val]; +} + +- (id)valueInExportFormat { + return [self.node.node valForExport:YES]; +} + +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString { + [FValidation validateFrom:@"child:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + FIRDatabaseReference *childRef = [self.ref child:childPathString]; + + id childNode = [self.node.node getChild:childPath]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:childNode]]; +} + +- (BOOL)hasChild:(NSString *)childPathString { + [FValidation validateFrom:@"hasChild:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + return ![[self.node.node getChild:childPath] isEmpty]; +} + +- (id)priority { + id priority = [self.node.node getPriority]; + return priority.val; +} + +- (BOOL)hasChildren { + if ([self.node.node isLeafNode]) { + return false; + } else { + return ![self.node.node isEmpty]; + } +} + +- (BOOL)exists { + return ![self.node.node isEmpty]; +} + +- (NSString *)key { + return [self.ref key]; +} + +- (NSUInteger)childrenCount { + return [self.node.node numChildren]; +} + +- (NSEnumerator *)children { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.node.childEnumerator + andTransform:^id(FNamedNode *node) { + FIRDatabaseReference *childRef = [self.ref child:node.name]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:node.node]]; + }]; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"Snap (%@) %@", self.key, self.node.node]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m new file mode 100644 index 00000000..01561e9c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m @@ -0,0 +1,229 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Auth/Public/FIRAuthInterop.h" + +#import "FIRDatabase.h" +#import "FIRDatabaseComponent.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoInfo.h" +#import "FValidation.h" + +@implementation FIRDatabase + +// The STR and STR_EXPAND macro allow a numeric version passed to he compiler +// driver with a -D to be treated as a string instead of an invalid floating +// point value. +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); + ++ (FIRDatabase *)database { + if (![FIRApp isDefaultAppConfigured]) { + [NSException raise:@"FIRAppNotConfigured" + format:@"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp " + @"configure]` (`FirebaseApp.configure()` in Swift) " + @"before using " + @"Firebase Database."]; + } + return [FIRDatabase databaseForApp:[FIRApp defaultApp]]; +} + ++ (FIRDatabase *)databaseWithURL:(NSString *)url { + FIRApp *app = [FIRApp defaultApp]; + if (app == nil) { + [NSException + raise:@"FIRAppNotConfigured" + format: + @"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp configure]` (`FirebaseApp.configure()` in " + @"Swift) before using Firebase Database."]; + } + return [FIRDatabase databaseForApp:app URL:url]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + return [FIRDatabase databaseForApp:app URL:app.options.databaseURL]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + @"Specify DatabaseURL within FIRApp or from your " + @"databaseForApp:URL: call."]; + } + id provider = + FIR_COMPONENT(FIRDatabaseProvider, app.container); + return [provider databaseForApp:app URL:url]; +} + ++ (NSString *)buildVersion { + // TODO: Restore git hash when build moves back to git + return [NSString stringWithFormat:@"%s_%s", FIREBASE_SEMVER, __DATE__]; +} + ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config { + FIRDatabase *db = [[FIRDatabase alloc] initWithApp:nil + repoInfo:repoInfo + config:config]; + [db ensureRepo]; + return db; +} + ++ (NSString *)sdkVersion { + return [NSString stringWithUTF8String:FIREBASE_SEMVER]; +} + ++ (void)setLoggingEnabled:(BOOL)enabled { + [FUtilities setLoggingEnabled:enabled]; + FFLog(@"I-RDB024001", @"BUILD Version: %@", [FIRDatabase buildVersion]); +} + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self != nil) { + self->_repoInfo = info; + self->_config = config; + self->_app = app; + } + return self; +} + +- (FIRDatabaseReference *)reference { + [self ensureRepo]; + + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:[FPath empty]]; +} + +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path { + [self ensureRepo]; + + [FValidation validateFrom:@"referenceWithPath" validRootPathString:path]; + FPath *childPath = [[FPath alloc] initWith:path]; + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:childPath]; +} + +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl { + [self ensureRepo]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"Invalid nil url passed to referenceFromURL:"]; + } + FParsedUrl *parsedUrl = [FUtilities parseUrl:databaseUrl]; + [FValidation validateFrom:@"referenceFromURL:" validURL:parsedUrl]; + if (![parsedUrl.repoInfo.host isEqualToString:_repoInfo.host]) { + [NSException + raise:@"InvalidDatabaseURL" + format: + @"Invalid URL (%@) passed to getReference(). URL was expected " + "to match configured Database URL: %@", + databaseUrl, [self reference].URL]; + } + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parsedUrl.path]; +} + +- (void)purgeOutstandingWrites { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo purgeOutstandingWrites]; + }); +} + +- (void)goOnline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo resume]; + }); +} + +- (void)goOffline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo interrupt]; + }); +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen:@"setPersistenceEnabled"]; + self->_config.persistenceEnabled = persistenceEnabled; +} + +- (BOOL)persistenceEnabled { + return self->_config.persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen:@"setPersistenceCacheSizeBytes"]; + self->_config.persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (NSUInteger)persistenceCacheSizeBytes { + return self->_config.persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen:@"setCallbackQueue"]; + self->_config.callbackQueue = callbackQueue; +} + +- (dispatch_queue_t)callbackQueue { + return self->_config.callbackQueue; +} + +- (void)assertUnfrozen:(NSString *)methodName { + if (self.repo != nil) { + [NSException + raise:@"FIRDatabaseAlreadyInUse" + format:@"Calls to %@ must be made before any other usage of " + "FIRDatabase instance.", + methodName]; + } +} + +- (void)ensureRepo { + if (self.repo == nil) { + self.repo = [FRepoManager createRepo:self.repoInfo + config:self.config + database:self]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h new file mode 100644 index 00000000..9d8bdb2c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRDatabase; + +NS_ASSUME_NONNULL_BEGIN + +/// This protocol is used in the interop registration process to register an +/// instance provider for individual FIRApps. +@protocol FIRDatabaseProvider + +/// Gets a FirebaseDatabase instance for the specified URL, using the specified +/// FirebaseApp. +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url; + +@end + +/// A concrete implementation for FIRDatabaseProvider to create Database +/// instances. +@interface FIRDatabaseComponent : NSObject + +/// The FIRApp that instances will be set up with. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable, use `databaseForApp:URL:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m new file mode 100644 index 00000000..59f89d54 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m @@ -0,0 +1,169 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseComponent.h" + +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoManager.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Auth/Public/FIRAuthInterop.h" + +NS_ASSUME_NONNULL_BEGIN + +/** A NSMutableDictionary of FirebaseApp name and FRepoInfo to FirebaseDatabase + * instance. */ +typedef NSMutableDictionary FIRDatabaseDictionary; + +@interface FIRDatabaseComponent () +@property(nonatomic) FIRDatabaseDictionary *instances; +/// Internal intializer. +- (instancetype)initWithApp:(FIRApp *)app; +@end + +@implementation FIRDatabaseComponent + +#pragma mark - Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + self = [super init]; + if (self) { + _app = app; + _instances = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Lifecycle + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-db" + withVersion:[FIRDatabase sdkVersion]]; +} + +#pragma mark - FIRComponentRegistrant + ++ (NSArray *)componentsToRegister { + FIRDependency *authDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop) + isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + return [[FIRDatabaseComponent alloc] initWithApp:container.app]; + }; + FIRComponent *databaseProvider = + [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ authDep ] + creationBlock:creationBlock]; + return @[ databaseProvider ]; +} + +#pragma mark - Instance management. + +- (void)appWillBeDeleted:(FIRApp *)app { + NSString *appName = app.name; + if (appName == nil) { + return; + } + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + // Clean up the deleted instance in an effort to remove any resources + // still in use. Note: Any leftover instances of this exact database + // will be invalid. + for (FIRDatabase *database in [instances allValues]) { + [FRepoManager disposeRepos:database.config]; + } + [instances removeAllObjects]; + } +} + +#pragma mark - FIRDatabaseProvider Conformance + +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + "Specify DatabaseURL within FIRApp or from your " + "databaseForApp:URL: call."]; + } + + NSURL *databaseUrl = [NSURL URLWithString:url]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"The Database URL '%@' cannot be parsed. " + "Specify a valid DatabaseURL within FIRApp or from " + "your databaseForApp:URL: call.", + databaseUrl]; + } else if (![databaseUrl.path isEqualToString:@""] && + ![databaseUrl.path isEqualToString:@"/"]) { + [NSException + raise:@"InvalidDatabaseURL" + format:@"Configured Database URL '%@' is invalid. It should point " + "to the root of a Firebase Database but it includes a " + "path: %@", + databaseUrl, databaseUrl.path]; + } + + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:databaseUrl.absoluteString]; + NSString *urlIndex = + [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host, + [parsedUrl.path toString]]; + FIRDatabase *database = instances[urlIndex]; + if (!database) { + id authTokenProvider = [FAuthTokenProvider + authTokenProviderWithAuth:FIR_COMPONENT(FIRAuthInterop, + app.container)]; + + // If this is the default app, don't set the session persistence key + // so that we use our default ("default") instead of the FIRApp + // default ("[DEFAULT]") so that we preserve the default location + // used by the legacy Firebase SDK. + NSString *sessionIdentifier = @"default"; + if (![FIRApp isDefaultAppConfigured] || + app != [FIRApp defaultApp]) { + sessionIdentifier = app.name; + } + + FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc] + initWithSessionIdentifier:sessionIdentifier + googleAppID:app.options.googleAppID + authTokenProvider:authTokenProvider]; + database = [[FIRDatabase alloc] initWithApp:app + repoInfo:parsedUrl.repoInfo + config:config]; + instances[urlIndex] = database; + } + + return database; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h new file mode 100644 index 00000000..16e4465b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FAuthTokenProvider; + +NS_ASSUME_NONNULL_BEGIN + +/** + * TODO: Merge FIRDatabaseConfig into FIRDatabase. + */ +@interface FIRDatabaseConfig : NSObject + +- (id)initWithSessionIdentifier:(NSString *)identifier + googleAppID:(NSString *)googleAppID + authTokenProvider:(id)authTokenProvider; + +/** + * By default the Firebase Database client will keep data in memory while your + * application is running, but not when it is restarted. By setting this value + * to YES, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first FIRDatabaseReference and only needs to be called once per + * application. + * + * If your app uses Firebase Authentication, the client will automatically + * persist the user's authentication token across restarts, even without + * persistence enabled. But if the auth token expired while offline and you've + * enabled persistence, the client will pause write operations until you + * successfully re-authenticate (or explicitly unauthenticate) to prevent your + * writes from being sent unauthenticated and failing due to security rules. + */ +@property(nonatomic) BOOL persistenceEnabled; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m new file mode 100644 index 00000000..8db9b74c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRNoopAuthTokenProvider.h" + +@interface FIRDatabaseConfig (Private) + +@property(nonatomic, strong, readwrite) NSString *sessionIdentifier; +@property(nonatomic, strong, readwrite) NSString *googleAppID; + +@end + +@implementation FIRDatabaseConfig + +- (id)init { + [NSException raise:NSInvalidArgumentException + format:@"Can't create config objects!"]; + return nil; +} + +- (id)initWithSessionIdentifier:(NSString *)identifier + googleAppID:(NSString *)googleAppID + authTokenProvider:(id)authTokenProvider { + self = [super init]; + if (self != nil) { + self->_sessionIdentifier = identifier; + self->_callbackQueue = dispatch_get_main_queue(); + self->_googleAppID = googleAppID; + self->_persistenceCacheSizeBytes = + 10 * 1024 * 1024; // Default cache size is 10MB + self->_authTokenProvider = authTokenProvider; + } + return self; +} + +- (void)assertUnfrozen { + if (self.isFrozen) { + [NSException raise:NSGenericException + format:@"Can't modify config objects after they are in use " + @"for FIRDatabaseReferences."]; + } +} + +- (void)setAuthTokenProvider:(id)authTokenProvider { + [self assertUnfrozen]; + self->_authTokenProvider = authTokenProvider; +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen]; + self->_persistenceEnabled = persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen]; + // Can't be less than 1MB + if (persistenceCacheSizeBytes < 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"The minimum cache size must be at least 1MB"]; + } + if (persistenceCacheSizeBytes > 100 * 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"Firebase Database currently doesn't support a " + @"cache size larger than 100MB"]; + } + self->_persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen]; + self->_callbackQueue = callbackQueue; +} + +- (void)freeze { + self->_isFrozen = YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m new file mode 100644 index 00000000..cd62979c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m @@ -0,0 +1,677 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FChildEventRegistration.h" +#import "FConstants.h" +#import "FIRDatabaseQuery_Private.h" +#import "FKeyIndex.h" +#import "FLeafNode.h" +#import "FPath.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FSnapshotUtilities.h" +#import "FValidation.h" +#import "FValueEventRegistration.h" +#import "FValueIndex.h" + +@implementation FIRDatabaseQuery + +@synthesize repo; +@synthesize path; +@synthesize queryParams; + +#define INVALID_QUERY_PARAM_ERROR @"InvalidQueryParameter" + ++ (dispatch_queue_t)sharedQueue { + // We use this shared queue across all of the FQueries so things happen FIFO + // (as opposed to dispatch_get_global_queue(0, 0) which is concurrent) + static dispatch_once_t pred; + static dispatch_queue_t sharedDispatchQueue; + + dispatch_once(&pred, ^{ + sharedDispatchQueue = dispatch_queue_create("FirebaseWorker", NULL); + }); + + return sharedDispatchQueue; +} + +- (id)initWithRepo:(FRepo *)theRepo path:(FPath *)thePath { + return [self initWithRepo:theRepo + path:thePath + params:nil + orderByCalled:NO + priorityMethodCalled:NO]; +} + +- (id)initWithRepo:(FRepo *)theRepo + path:(FPath *)thePath + params:(FQueryParams *)theParams + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled { + self = [super init]; + if (self) { + self.repo = theRepo; + self.path = thePath; + if (!theParams) { + theParams = [FQueryParams defaultInstance]; + } + if (![theParams isValid]) { + @throw [[NSException alloc] + initWithName:@"InvalidArgumentError" + reason:@"Queries are limited to two constraints" + userInfo:nil]; + } + self.queryParams = theParams; + self.orderByCalled = orderByCalled; + self.priorityMethodCalled = priorityMethodCalled; + } + return self; +} + +- (FQuerySpec *)querySpec { + return [[FQuerySpec alloc] initWithPath:self.path params:self.queryParams]; +} + +- (void)validateQueryEndpointsForParams:(FQueryParams *)params { + if ([params.index isEqual:[FKeyIndex keyIndex]]) { + if ([params hasStart]) { + if (params.indexStartKey != [FUtilities minName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryStartingAtValue:childKey: " + @"or queryEqualTo:andChildKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexStartValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryStartingAtValue: with other types " + @"than string in combination with queryOrderedByKey"]; + } + } + if ([params hasEnd]) { + if (params.indexEndKey != [FUtilities maxName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryEndingAtValue:childKey: or " + @"queryEqualToValue:childKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexEndValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryEndingAtValue: with other types than " + @"string in combination with queryOrderedByKey"]; + } + } + } else if ([params.index isEqual:[FPriorityIndex priorityIndex]]) { + if (([params hasStart] && + ![FValidation validatePriorityValue:params.indexStartValue.val]) || + ([params hasEnd] && + ![FValidation validatePriorityValue:params.indexEndValue.val])) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format:@"When using queryOrderedByPriority, values provided to " + @"queryStartingAtValue:, queryEndingAtValue:, or " + @"queryEqualToValue: must be valid priorities."]; + } + } +} + +- (void)validateEqualToCall { + if ([self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryStartingAtValue:"]; + } + if ([self.queryParams hasEnd]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryEndingAtValue:"]; + } +} + +- (void)validateNoPreviousOrderByCalled { + if (self.orderByCalled) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Cannot use multiple queryOrderedBy calls!"]; + } +} + +- (void)validateIndexValueType:(id)type fromMethod:(NSString *)method { + if (type != nil && ![type isKindOfClass:[NSNumber class]] && + ![type isKindOfClass:[NSString class]] && + ![type isKindOfClass:[NSNull class]]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"You can only pass nil, NSString or NSNumber to %@", + method]; + } +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [self queryStartingAtInternal:startValue + childKey:nil + from:@"queryStartingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryStartingAtValue: instead of " + @"queryStartingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + return [self queryStartingAtInternal:startValue + childKey:childKey + from:@"queryStartingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtInternal:(id)startValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:startValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasStart]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryStartingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id startNode = [FSnapshotUtilities nodeFrom:startValue]; + FQueryParams *params = [self.queryParams startAt:startNode + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [self queryEndingAtInternal:endValue + childKey:nil + from:@"queryEndingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEndingAtValue: instead of " + @"queryEndingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + + return [self queryEndingAtInternal:endValue + childKey:childKey + from:@"queryEndingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtInternal:(id)endValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:endValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryEndingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id endNode = [FSnapshotUtilities nodeFrom:endValue]; + FQueryParams *params = [self.queryParams endAt:endNode childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [self queryEqualToInternal:value + childKey:nil + from:@"queryEqualToValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEqualToValue: instead of " + @"queryEqualTo:childKey: when using queryOrderedByKey:" + userInfo:nil]; + } + return [self queryEqualToInternal:value + childKey:childKey + from:@"queryEqualToValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToInternal:(id)value + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:value fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd] || [self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't call %@ after queryStartingAtValue, queryEndingAtValue " + @"or queryEqualToValue was previously called", + methodName]; + } + id node = [FSnapshotUtilities nodeFrom:value]; + FQueryParams *params = [[self.queryParams startAt:node + childKey:childKey] endAt:node + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (void)validateLimitRange:(NSUInteger)limit { + // No need to check for negative ranges, since limit is unsigned + if (limit == 0) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit can't be zero"]; + } + if (limit >= 1ul << 31) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit must be less than 2,147,483,648"]; + } +} + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToFirst: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToFirst:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToLast: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToLast:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)indexPathString { + if ([indexPathString isEqualToString:@"$key"] || + [indexPathString isEqualToString:@".key"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByKey: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$priority"] || + [indexPathString isEqualToString:@".priority"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByPriority: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$value"] || + [indexPathString isEqualToString:@".value"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByValue: instead.", + indexPathString] + userInfo:nil]; + } + [self validateNoPreviousOrderByCalled]; + + [FValidation validateFrom:@"queryOrderedByChild:" + validPathString:indexPathString]; + FPath *indexPath = [FPath pathWithString:indexPathString]; + if (indexPath.isEmpty) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString + stringWithFormat:@"(queryOrderedByChild:) with an " + @"empty path is invalid. Use " + @"queryOrderedByValue: instead."] + userInfo:nil]; + } + id index = [[FPathIndex alloc] initWithPath:indexPath]; + + FQueryParams *params = [self.queryParams orderBy:index]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FKeyIndex keyIndex]]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByValue { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FValueIndex valueIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = + [self.queryParams orderBy:[FPriorityIndex priorityIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *))block { + [FValidation validateFrom:@"observeEventType:withBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [FValidation + validateFrom:@"observeEventType:andPreviousSiblingKeyWithBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:withBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // Handle FIRDataEventTypeValue specially because they shouldn't have + // prevName callbacks + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + [self observeValueEventWithHandle:handle + withBlock:block + cancelCallback:cancelBlock]; + return handle; + } else { + // Wrap up the userCallback so we can treat everything as a callback + // that has a prevName + fbt_void_datasnapshot userCallback = [block copy]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (userCallback != nil) { + userCallback(snapshot); + } + } + withCancelBlock:cancelBlock]; + } +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:" + @"andPreviousSiblingKeyWithBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // TODO: This gets hit by observeSingleEventOfType. Need to fix. + /* + @throw [[NSException alloc] initWithName:@"InvalidEventTypeForObserver" + reason:@"(observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock:) + Cannot use + observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock: with + FIRDataEventTypeValue. Use observeEventType:withBlock:withCancelBlock: + instead." userInfo:nil]; + */ + } + + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + NSDictionary *callbacks = + @{[NSNumber numberWithInteger:eventType] : [block copy]}; + [self observeChildEventWithHandle:handle + withCallbacks:callbacks + cancelCallback:cancelBlock]; + + return handle; +} + +// If we want to distinguish between value event listeners and child event +// listeners, like in the Java client, we can consider exporting this. If we do, +// add argument validation. Otherwise, arguments are validated in the +// public-facing portions of the API. Also, move the FIRDatabaseHandle logic. +- (void)observeValueEventWithHandle:(FIRDatabaseHandle)handle + withBlock:(fbt_void_datasnapshot)block + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:block + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +// Note: as with the above method, we may wish to expose this at some point. +- (void)observeChildEventWithHandle:(FIRDatabaseHandle)handle + withCallbacks:(NSDictionary *)callbacks + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FChildEventRegistration *registration = + [[FChildEventRegistration alloc] initWithRepo:self.repo + handle:handle + callbacks:callbacks + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + FValueEventRegistration *event = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:nil + cancelCallback:nil]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo removeEventRegistration:event forQuery:self.querySpec]; + }); +} + +- (void)removeAllObservers { + [self removeObserverWithHandle:NSNotFound]; +} + +- (void)keepSynced:(BOOL)keepSynced { + if ([self.path.getFront isEqualToString:kDotInfoPrefix]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't keep query on .info tree synced (this " + @"already is the case)."]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo keepQuery:self.querySpec synced:keepSynced]; + }); +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (block != nil) { + block(snapshot); + } + } + withCancelBlock:cancelBlock]; +} + +/** + * Attaches a listener, waits for the first event, and then removes the listener + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + __block FIRDatabaseHandle handle; + __block BOOL firstCall = YES; + + fbt_void_datasnapshot_nsstring callback = [block copy]; + fbt_void_datasnapshot_nsstring wrappedCallback = + ^(FIRDataSnapshot *snap, NSString *prevName) { + if (firstCall) { + firstCall = NO; + [self removeObserverWithHandle:handle]; + callback(snap, prevName); + } + }; + + fbt_void_nserror cancelCallback = [cancelBlock copy]; + handle = [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:wrappedCallback + withCancelBlock:^(NSError *error) { + [self removeObserverWithHandle:handle]; + + if (cancelCallback) { + cancelCallback(error); + } + }]; +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"(%@ %@)", self.path, self.queryParams.description]; +} + +- (FIRDatabaseReference *)ref { + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:self.path]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m new file mode 100644 index 00000000..5da7fae5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m @@ -0,0 +1,149 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FChildrenNode.h" +#import "FIRMutableData_Private.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FTransformedEnumerator.h" + +@interface FIRMutableData () + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder; + +@property(strong, nonatomic) FSnapshotHolder *data; +@property(strong, nonatomic) FPath *prefixPath; + +@end + +@implementation FIRMutableData + +@synthesize data; +@synthesize prefixPath; + +- (id)initWithNode:(id)node { + FSnapshotHolder *holder = [[FSnapshotHolder alloc] init]; + FPath *path = [FPath empty]; + [holder updateSnapshot:path withNewSnapshot:node]; + return [self initWithPrefixPath:path andSnapshotHolder:holder]; +} + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder { + self = [super init]; + if (self) { + self.prefixPath = path; + self.data = snapshotHolder; + } + return self; +} + +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path { + FPath *wholePath = [self.prefixPath childFromString:path]; + return [[FIRMutableData alloc] initWithPrefixPath:wholePath + andSnapshotHolder:self.data]; +} + +- (FIRMutableData *)parent { + if ([self.prefixPath isEmpty]) { + return nil; + } else { + FPath *path = [self.prefixPath parent]; + return [[FIRMutableData alloc] initWithPrefixPath:path + andSnapshotHolder:self.data]; + } +} + +- (void)setValue:(id)aValue { + id node = [FSnapshotUtilities nodeFrom:aValue + withValidationFrom:@"setValue:"]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (void)setPriority:(id)aPriority { + id node = [self.data getNode:self.prefixPath]; + id pri = [FSnapshotUtilities nodeFrom:aPriority]; + node = [node updatePriority:pri]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (id)value { + return [[self.data getNode:self.prefixPath] val]; +} + +- (id)priority { + return [[[self.data getNode:self.prefixPath] getPriority] val]; +} + +- (BOOL)hasChildren { + id node = [self.data getNode:self.prefixPath]; + return ![node isLeafNode] && ![(FChildrenNode *)node isEmpty]; +} + +- (BOOL)hasChildAtPath:(NSString *)path { + id node = [self.data getNode:self.prefixPath]; + FPath *childPath = [[FPath alloc] initWith:path]; + return ![[node getChild:childPath] isEmpty]; +} + +- (NSUInteger)childrenCount { + return [[self.data getNode:self.prefixPath] numChildren]; +} + +- (NSString *)key { + return [self.prefixPath getBack]; +} + +- (id)nodeValue { + return [self.data getNode:self.prefixPath]; +} + +- (NSEnumerator *)children { + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:self.nodeValue]; + return [[FTransformedEnumerator alloc] + initWithEnumerator:[indexedNode childEnumerator] + andTransform:^id(FNamedNode *node) { + FPath *childPath = [self.prefixPath childFromString:node.name]; + FIRMutableData *childData = + [[FIRMutableData alloc] initWithPrefixPath:childPath + andSnapshotHolder:self.data]; + return childData; + }]; +} + +- (BOOL)isEqualToData:(FIRMutableData *)other { + return self.data == other.data && + [[self.prefixPath description] + isEqualToString:[other.prefixPath description]]; +} + +- (NSString *)description { + if (self.key == nil) { + return [NSString + stringWithFormat:@"FIRMutableData (top-most transaction) %@ %@", + self.key, self.value]; + } else { + return [NSString + stringWithFormat:@"FIRMutableData (%@) %@", self.key, self.value]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m new file mode 100644 index 00000000..928dae09 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRServerValue.h" + +@implementation FIRServerValue + ++ (NSDictionary *)timestamp { + static NSDictionary *timestamp = nil; + if (timestamp == nil) { + timestamp = @{@".sv" : @"timestamp"}; + } + return timestamp; +} + ++ (NSDictionary *)increment:(NSNumber *)delta { + return @{@".sv" : @{@"increment" : delta}}; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m new file mode 100644 index 00000000..9fec8626 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" + +@implementation FIRTransactionResult + +@synthesize update; +@synthesize isSuccess; + ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = YES; + result.update = value; + return result; +} + ++ (FIRTransactionResult *)abort { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = NO; + result.update = nil; + return result; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h new file mode 100644 index 00000000..ac23045b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIndexedNode.h" +#import "FTypedefs_Private.h" + +@interface FIRDataSnapshot () + +// in _Private for testing purposes +@property(nonatomic, strong) FIndexedNode *node; + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h new file mode 100644 index 00000000..30f19f02 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseQuery () + ++ (dispatch_queue_t)sharedQueue; + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; +- (id)initWithRepo:(FRepo *)repo + path:(FPath *)path + params:(FQueryParams *)params + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled; + +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) FQueryParams *queryParams; +@property(nonatomic) BOOL orderByCalled; +@property(nonatomic) BOOL priorityMethodCalled; + +- (FQuerySpec *)querySpec; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h new file mode 100644 index 00000000..1d7e37c7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseReference.h" +#import "FRepo.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseReference () + +- (id)initWithConfig:(FIRDatabaseConfig *)config; +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h new file mode 100644 index 00000000..0ff3e70f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabase.h" + +@class FRepo; +@class FRepoInfo; +@class FIRDatabaseConfig; + +@interface FIRDatabase () + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic, strong) FRepo *repo; + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config; + ++ (NSString *)buildVersion; ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h new file mode 100644 index 00000000..fded102f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FNode.h" + +@interface FIRMutableData () + +- (id)initWithNode:(id)node; +- (id)nodeValue; +- (BOOL)isEqualToData:(FIRMutableData *)other; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h new file mode 100644 index 00000000..bdf250ac --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FIRTransactionResult.h" + +@interface FIRTransactionResult () + +@property(nonatomic) BOOL isSuccess; +@property(nonatomic, strong) FIRMutableData *update; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h new file mode 100644 index 00000000..dac55bcc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FTYPEDEFS_PRIVATE__ +#define __FTYPEDEFS_PRIVATE__ + +#import + +typedef NS_ENUM(NSInteger, FTransactionStatus) { + FTransactionInitializing, // 0 + FTransactionRun, // 1 + FTransactionSent, // 2 + FTransactionCompleted, // 3 + FTransactionSentNeedsAbort, // 4 + FTransactionNeedsAbort // 5 +}; + +@protocol FNode; +@class FPath; +@class FIRTransactionResult; +@class FIRMutableData; +@class FIRDataSnapshot; +@class FCompoundHash; + +typedef void (^fbt_void_nserror_bool_datasnapshot)(NSError *error, + BOOL committed, + FIRDataSnapshot *snapshot); +typedef FIRTransactionResult * (^fbt_transactionresult_mutabledata)( + FIRMutableData *currentData); +typedef void (^fbt_void_path_node)(FPath *, id); +typedef void (^fbt_void_nsstring)(NSString *); +typedef BOOL (^fbt_bool_nsstring_node)(NSString *, id); +typedef void (^fbt_void_path_node_marray)(FPath *, id, NSMutableArray *); +typedef BOOL (^fbt_bool_void)(void); +typedef void (^fbt_void_nsstring_nsstring)(NSString *str1, NSString *str2); +typedef void (^fbt_void_nsstring_nserror)(NSString *str, NSError *error); +typedef BOOL (^fbt_bool_path)(FPath *str); +typedef void (^fbt_void_id)(id data); +typedef NSString * (^fbt_nsstring_void)(void); +typedef FCompoundHash * (^fbt_compoundhash_void)(void); +typedef NSArray * (^fbt_nsarray_nsstring_id)(NSString *status, id Data); +typedef NSArray * (^fbt_nsarray_nsstring)(NSString *status); + +// WWDC 2012 session 712 starting in page 83 for saving blocks in properties +// (use @property (strong) type name). + +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h new file mode 100644 index 00000000..ae237a6c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h @@ -0,0 +1,195 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FConstants_h +#define Firebase_FConstants_h + +#import + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestType; +FOUNDATION_EXPORT NSString *const kFWPRequestTypeData; +FOUNDATION_EXPORT NSString *const kFWPRequestDataPayload; +FOUNDATION_EXPORT NSString *const kFWPRequestNumber; +FOUNDATION_EXPORT NSString *const kFWPRequestPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPRequestError; +FOUNDATION_EXPORT NSString *const kFWPRequestAction; +FOUNDATION_EXPORT NSString *const kFWPResponseForRNData; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatus; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusOk; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusDataStale; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionData; +FOUNDATION_EXPORT NSString *const kFWPResponseDataWarnings; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAction; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdate; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAuthRevoked; +FOUNDATION_EXPORT NSString *const kFWPASyncServerListenCancelled; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerSecurityDebug; +FOUNDATION_EXPORT NSString + *const kFWPAsyncServerDataUpdateBodyPath; // {"a": "d", "b": {"p": "/", "d": + // """}} +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateStartPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateEndPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyTag; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataQueries; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessage; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMessage; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHello; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloTimestamp; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloVersion; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloConnectedHost; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloSession; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageShutdown; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageReset; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestActionPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedListen; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedUnlisten; +FOUNDATION_EXPORT NSString + *const kFWPRequestActionListen; // {"t": "d", "d": {"r": 1, "a": "l", "b": { + // "p": "/" } } } +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnlisten; +FOUNDATION_EXPORT NSString *const kFWPRequestActionStats; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectCancel; +FOUNDATION_EXPORT NSString *const kFWPRequestActionAuth; +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnauth; +FOUNDATION_EXPORT NSString *const kFWPRequestCredential; +FOUNDATION_EXPORT NSString *const kFWPRequestPath; +FOUNDATION_EXPORT NSString *const kFWPRequestCounters; +FOUNDATION_EXPORT NSString *const kFWPRequestQueries; +FOUNDATION_EXPORT NSString *const kFWPRequestTag; +FOUNDATION_EXPORT NSString *const kFWPRequestData; +FOUNDATION_EXPORT NSString *const kFWPRequestHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashPaths; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashHashes; +FOUNDATION_EXPORT NSString *const kFWPRequestStatus; + +#pragma mark - +#pragma mark Websock Transport Constants + +FOUNDATION_EXPORT NSString *const kWireProtocolVersionParam; +FOUNDATION_EXPORT NSString *const kWebsocketProtocolVersion; +FOUNDATION_EXPORT NSString *const kWebsocketServerKillPacket; +FOUNDATION_EXPORT const int kWebsocketMaxFrameSize; +FOUNDATION_EXPORT NSUInteger const kWebsocketKeepaliveInterval; +FOUNDATION_EXPORT NSUInteger const kWebsocketConnectTimeout; + +FOUNDATION_EXPORT float const kPersistentConnReconnectMinDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMaxDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMultiplier; +FOUNDATION_EXPORT float const + kPersistentConnSuccessfulConnectionEstablishedDelay; + +#pragma mark - +#pragma mark Query / QueryParams constants + +FOUNDATION_EXPORT NSString *const kQueryDefault; +FOUNDATION_EXPORT NSString *const kQueryDefaultObject; +FOUNDATION_EXPORT NSString *const kViewManagerDictConstView; +FOUNDATION_EXPORT NSString *const kFQPIndexStartValue; +FOUNDATION_EXPORT NSString *const kFQPIndexStartName; +FOUNDATION_EXPORT NSString *const kFQPIndexEndValue; +FOUNDATION_EXPORT NSString *const kFQPIndexEndName; +FOUNDATION_EXPORT NSString *const kFQPLimit; +FOUNDATION_EXPORT NSString *const kFQPViewFrom; +FOUNDATION_EXPORT NSString *const kFQPViewFromLeft; +FOUNDATION_EXPORT NSString *const kFQPViewFromRight; +FOUNDATION_EXPORT NSString *const kFQPIndex; + +#pragma mark - +#pragma mark Interrupt Reasons + +FOUNDATION_EXPORT NSString *const kFInterruptReasonServerKill; +FOUNDATION_EXPORT NSString *const kFInterruptReasonWaitingForOpen; +FOUNDATION_EXPORT NSString *const kFInterruptReasonRepoInterrupt; +FOUNDATION_EXPORT NSString *const kFInterruptReasonAuthExpired; + +#pragma mark - +#pragma mark Payload constants + +FOUNDATION_EXPORT NSString *const kPayloadPriority; +FOUNDATION_EXPORT NSString *const kPayloadValue; +FOUNDATION_EXPORT NSString *const kPayloadMetadataPrefix; + +#pragma mark - +#pragma mark ServerValue constants + +FOUNDATION_EXPORT NSString *const kServerValueSubKey; +FOUNDATION_EXPORT NSString *const kServerValuePriority; + +#pragma mark - +#pragma mark.info/ constants + +FOUNDATION_EXPORT NSString *const kDotInfoPrefix; +FOUNDATION_EXPORT NSString *const kDotInfoConnected; +FOUNDATION_EXPORT NSString *const kDotInfoServerTimeOffset; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +FOUNDATION_EXPORT NSString *const kJavaScriptObject; +FOUNDATION_EXPORT NSString *const kJavaScriptString; +FOUNDATION_EXPORT NSString *const kJavaScriptBoolean; +FOUNDATION_EXPORT NSString *const kJavaScriptNumber; +FOUNDATION_EXPORT NSString *const kJavaScriptNull; +FOUNDATION_EXPORT NSString *const kJavaScriptTrue; +FOUNDATION_EXPORT NSString *const kJavaScriptFalse; + +#pragma mark - +#pragma mark Error handling constants + +FOUNDATION_EXPORT NSString *const kFErrorDomain; +FOUNDATION_EXPORT NSUInteger const kFAuthError; +FOUNDATION_EXPORT NSString *const kFErrorWriteCanceled; + +#pragma mark - +#pragma mark Validation Constants + +FOUNDATION_EXPORT NSUInteger const kFirebaseMaxObjectDepth; +FOUNDATION_EXPORT const unsigned int kFirebaseMaxLeafSize; + +#pragma mark - +#pragma mark Transaction Constants + +FOUNDATION_EXPORT NSUInteger const kFTransactionMaxRetries; +FOUNDATION_EXPORT NSString *const kFTransactionTooManyRetries; +FOUNDATION_EXPORT NSString *const kFTransactionNoData; +FOUNDATION_EXPORT NSString *const kFTransactionSet; +FOUNDATION_EXPORT NSString *const kFTransactionDisconnect; + +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m new file mode 100644 index 00000000..23439917 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m @@ -0,0 +1,185 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConstants.h" + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +NSString *const kFWPRequestType = @"t"; +NSString *const kFWPRequestTypeData = @"d"; +NSString *const kFWPRequestDataPayload = @"d"; +NSString *const kFWPRequestNumber = @"r"; +NSString *const kFWPRequestPayloadBody = @"b"; +NSString *const kFWPRequestError = @"error"; +NSString *const kFWPRequestAction = @"a"; +NSString *const kFWPResponseForRNData = @"b"; +NSString *const kFWPResponseForActionStatus = @"s"; +NSString *const kFWPResponseForActionStatusOk = @"ok"; +NSString *const kFWPResponseForActionStatusDataStale = @"datastale"; +NSString *const kFWPResponseForActionData = @"d"; +NSString *const kFWPResponseDataWarnings = @"w"; +NSString *const kFWPAsyncServerAction = @"a"; +NSString *const kFWPAsyncServerPayloadBody = @"b"; +NSString *const kFWPAsyncServerDataUpdate = @"d"; +NSString *const kFWPAsyncServerDataMerge = @"m"; +NSString *const kFWPAsyncServerDataRangeMerge = @"rm"; +NSString *const kFWPAsyncServerAuthRevoked = @"ac"; +NSString *const kFWPASyncServerListenCancelled = @"c"; +NSString *const kFWPAsyncServerSecurityDebug = @"sd"; +NSString *const kFWPAsyncServerDataUpdateBodyPath = + @"p"; // {"a": "d", "b": {"p": "/", "d": ""}} +NSString *const kFWPAsyncServerDataUpdateBodyData = @"d"; +NSString *const kFWPAsyncServerDataUpdateStartPath = @"s"; +NSString *const kFWPAsyncServerDataUpdateEndPath = @"e"; +NSString *const kFWPAsyncServerDataUpdateRangeMerge = @"m"; +NSString *const kFWPAsyncServerDataUpdateBodyTag = @"t"; +NSString *const kFWPAsyncServerDataQueries = @"q"; + +NSString *const kFWPAsyncServerEnvelopeType = @"t"; +NSString *const kFWPAsyncServerEnvelopeData = @"d"; +NSString *const kFWPAsyncServerControlMessage = @"c"; +NSString *const kFWPAsyncServerControlMessageType = @"t"; +NSString *const kFWPAsyncServerControlMessageData = @"d"; +NSString *const kFWPAsyncServerDataMessage = @"d"; + +NSString *const kFWPAsyncServerHello = @"h"; +NSString *const kFWPAsyncServerHelloTimestamp = @"ts"; +NSString *const kFWPAsyncServerHelloVersion = @"v"; +NSString *const kFWPAsyncServerHelloConnectedHost = @"h"; +NSString *const kFWPAsyncServerHelloSession = @"s"; + +NSString *const kFWPAsyncServerControlMessageShutdown = @"s"; +NSString *const kFWPAsyncServerControlMessageReset = @"r"; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +NSString *const kFWPRequestActionPut = @"p"; +NSString *const kFWPRequestActionMerge = @"m"; +NSString *const kFWPRequestActionListen = + @"l"; // {"t": "d", "d": {"r": 1, "a": "l", "b": { "p": "/" } } } +NSString *const kFWPRequestActionUnlisten = @"u"; +NSString *const kFWPRequestActionStats = @"s"; +NSString *const kFWPRequestActionTaggedListen = @"q"; +NSString *const kFWPRequestActionTaggedUnlisten = @"n"; +NSString *const kFWPRequestActionDisconnectPut = @"o"; +NSString *const kFWPRequestActionDisconnectMerge = @"om"; +NSString *const kFWPRequestActionDisconnectCancel = @"oc"; +NSString *const kFWPRequestActionAuth = @"auth"; +NSString *const kFWPRequestActionUnauth = @"unauth"; +NSString *const kFWPRequestCredential = @"cred"; +NSString *const kFWPRequestPath = @"p"; +NSString *const kFWPRequestCounters = @"c"; +NSString *const kFWPRequestQueries = @"q"; +NSString *const kFWPRequestTag = @"t"; +NSString *const kFWPRequestData = @"d"; +NSString *const kFWPRequestHash = @"h"; +NSString *const kFWPRequestCompoundHash = @"ch"; +NSString *const kFWPRequestCompoundHashPaths = @"ps"; +NSString *const kFWPRequestCompoundHashHashes = @"hs"; +NSString *const kFWPRequestStatus = @"s"; + +#pragma mark - +#pragma mark Websock Transport Constants + +NSString *const kWireProtocolVersionParam = @"v"; +NSString *const kWebsocketProtocolVersion = @"5"; +NSString *const kWebsocketServerKillPacket = @"kill"; +const int kWebsocketMaxFrameSize = 16384; +NSUInteger const kWebsocketKeepaliveInterval = 45; +NSUInteger const kWebsocketConnectTimeout = 30; + +float const kPersistentConnReconnectMinDelay = 1.0; +float const kPersistentConnReconnectMaxDelay = 30.0; +float const kPersistentConnReconnectMultiplier = 1.3f; +float const kPersistentConnSuccessfulConnectionEstablishedDelay = 30.0; + +#pragma mark - +#pragma mark Query constants + +NSString *const kQueryDefault = @"default"; +NSString *const kQueryDefaultObject = @"{}"; +NSString *const kViewManagerDictConstView = @"view"; +NSString *const kFQPIndexStartValue = @"sp"; +NSString *const kFQPIndexStartName = @"sn"; +NSString *const kFQPIndexEndValue = @"ep"; +NSString *const kFQPIndexEndName = @"en"; +NSString *const kFQPLimit = @"l"; +NSString *const kFQPViewFrom = @"vf"; +NSString *const kFQPViewFromLeft = @"l"; +NSString *const kFQPViewFromRight = @"r"; +NSString *const kFQPIndex = @"i"; + +#pragma mark - +#pragma mark Interrupt Reasons + +NSString *const kFInterruptReasonServerKill = @"server_kill"; +NSString *const kFInterruptReasonWaitingForOpen = @"waiting_for_open"; +NSString *const kFInterruptReasonRepoInterrupt = @"repo_interrupt"; + +#pragma mark - +#pragma mark Payload constants + +NSString *const kPayloadPriority = @".priority"; +NSString *const kPayloadValue = @".value"; +NSString *const kPayloadMetadataPrefix = @"."; + +#pragma mark - +#pragma mark ServerValue constants + +NSString *const kServerValueSubKey = @".sv"; +NSString *const kServerValuePriority = @"timestamp"; + +#pragma mark - +#pragma mark.info/ constants + +NSString *const kDotInfoPrefix = @".info"; +NSString *const kDotInfoConnected = @"connected"; +NSString *const kDotInfoServerTimeOffset = @"serverTimeOffset"; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +NSString *const kJavaScriptObject = @"object"; +NSString *const kJavaScriptString = @"string"; +NSString *const kJavaScriptBoolean = @"boolean"; +NSString *const kJavaScriptNumber = @"number"; +NSString *const kJavaScriptNull = @"null"; +NSString *const kJavaScriptTrue = @"true"; +NSString *const kJavaScriptFalse = @"false"; + +#pragma mark - +#pragma mark Error handling constants + +NSString *const kFErrorDomain = @"com.firebase"; +NSUInteger const kFAuthError = 1; +NSString *const kFErrorWriteCanceled = @"write_canceled"; + +#pragma mark - +#pragma mark Validation Constants + +NSUInteger const kFirebaseMaxObjectDepth = 1000; +const unsigned int kFirebaseMaxLeafSize = 1024 * 1024 * 10; // 10 MB + +#pragma mark - +#pragma mark Transaction Constants + +NSUInteger const kFTransactionMaxRetries = 25; +NSString *const kFTransactionTooManyRetries = @"maxretry"; +NSString *const kFTransactionNoData = @"nodata"; +NSString *const kFTransactionSet = @"set"; +NSString *const kFTransactionDisconnect = @"disconnect"; diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h new file mode 100644 index 00000000..2453a81a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +@interface FCompoundHashBuilder : NSObject + +- (FPath *)currentPath; + +@end + +typedef BOOL (^FCompoundHashSplitStrategy)(FCompoundHashBuilder *builder); + +@interface FCompoundHash : NSObject + +@property(nonatomic, strong, readonly) NSArray *posts; +@property(nonatomic, strong, readonly) NSArray *hashes; + ++ (FCompoundHash *)fromNode:(id)node; ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m new file mode 100644 index 00000000..ced79cd6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m @@ -0,0 +1,259 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundHash.h" +#import "FChildrenNode.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" + +@interface FCompoundHashBuilder () + +@property(nonatomic, strong) FCompoundHashSplitStrategy splitStrategy; + +@property(nonatomic, strong) NSMutableArray *currentPaths; +@property(nonatomic, strong) NSMutableArray *currentHashes; + +@end + +@implementation FCompoundHashBuilder { + + // NOTE: We use the existence of this to know if we've started building a + // range (i.e. encountered a leaf node). + NSMutableString *optHashValueBuilder; + + // The current path as a stack. This is used in combination with + // currentPathDepth to simultaneously store the last leaf node path. The + // depth is changed when descending and ascending, at the same time the + // current key is set for the current depth. Because the keys are left + // unchanged for ascending the path will also contain the path of the last + // visited leaf node (using lastLeafDepth elements) + NSMutableArray *currentPath; + NSInteger lastLeafDepth; + NSInteger currentPathDepth; + + BOOL needsComma; +} + +- (instancetype)initWithSplitStrategy:(FCompoundHashSplitStrategy)strategy { + self = [super init]; + if (self != nil) { + self->_splitStrategy = strategy; + self->optHashValueBuilder = nil; + self->currentPath = [NSMutableArray array]; + self->lastLeafDepth = -1; + self->currentPathDepth = 0; + self->needsComma = YES; + self->_currentPaths = [NSMutableArray array]; + self->_currentHashes = [NSMutableArray array]; + } + return self; +} + +- (BOOL)isBuildingRange { + return self->optHashValueBuilder != nil; +} + +- (NSUInteger)currentHashLength { + return self->optHashValueBuilder.length; +} + +- (FPath *)currentPath { + return [self currentPathWithDepth:self->currentPathDepth]; +} + +- (FPath *)currentPathWithDepth:(NSInteger)depth { + NSArray *pieces = + [self->currentPath subarrayWithRange:NSMakeRange(0, depth)]; + return [[FPath alloc] initWithPieces:pieces andPieceNum:0]; +} + +- (void)enumerateCurrentPathToDepth:(NSInteger)depth + withBlock:(void (^)(NSString *key))block { + for (NSInteger i = 0; i < depth; i++) { + block(self->currentPath[i]); + } +} + +- (void)appendKey:(NSString *)key toString:(NSMutableString *)string { + [FSnapshotUtilities appendHashV2RepresentationForString:key + toString:string]; +} + +- (void)ensureRange { + if (![self isBuildingRange]) { + optHashValueBuilder = [NSMutableString string]; + [optHashValueBuilder appendString:@"("]; + [self + enumerateCurrentPathToDepth:self->currentPathDepth + withBlock:^(NSString *key) { + [self appendKey:key + toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + }]; + self->needsComma = NO; + } +} + +- (void)processLeaf:(FLeafNode *)leafNode { + [self ensureRange]; + + self->lastLeafDepth = self->currentPathDepth; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode + toString:self->optHashValueBuilder + hashVersion:FDataHashVersionV2]; + self->needsComma = YES; + if (self.splitStrategy(self)) { + [self endRange]; + } +} + +- (void)startChild:(NSString *)key { + [self ensureRange]; + + if (self->needsComma) { + [self->optHashValueBuilder appendString:@","]; + } + [self appendKey:key toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + if (self->currentPathDepth == currentPath.count) { + [self->currentPath addObject:key]; + } else { + self->currentPath[self->currentPathDepth] = key; + } + self->currentPathDepth++; + self->needsComma = NO; +} + +- (void)endChild { + self->currentPathDepth--; + if ([self isBuildingRange]) { + [self->optHashValueBuilder appendString:@")"]; + } + self->needsComma = YES; +} + +- (void)finishHashing { + NSAssert(self->currentPathDepth == 0, + @"Can't finish hashing in the middle of processing a child"); + if ([self isBuildingRange]) { + [self endRange]; + } + + // Always close with the empty hash for the remaining range to allow simple + // appending + [self.currentHashes addObject:@""]; +} + +- (void)endRange { + NSAssert([self isBuildingRange], + @"Can't end range without starting a range!"); + // Add closing parenthesis for current depth + for (NSUInteger i = 0; i < currentPathDepth; i++) { + [self->optHashValueBuilder appendString:@")"]; + } + [self->optHashValueBuilder appendString:@")"]; + + FPath *lastLeafPath = [self currentPathWithDepth:self->lastLeafDepth]; + NSString *hash = + [FStringUtilities base64EncodedSha1:self->optHashValueBuilder]; + [self.currentHashes addObject:hash]; + [self.currentPaths addObject:lastLeafPath]; + + self->optHashValueBuilder = nil; +} + +@end + +@interface FCompoundHash () + +@property(nonatomic, strong, readwrite) NSArray *posts; +@property(nonatomic, strong, readwrite) NSArray *hashes; + +@end + +@implementation FCompoundHash + +- (id)initWithPosts:(NSArray *)posts hashes:(NSArray *)hashes { + self = [super init]; + if (self != nil) { + if (posts.count != hashes.count - 1) { + [NSException raise:NSInvalidArgumentException + format:@"Number of posts need to be n-1 for n hashes " + @"in FCompoundHash"]; + } + self.posts = posts; + self.hashes = hashes; + } + return self; +} + ++ (FCompoundHashSplitStrategy)simpleSizeSplitStrategyForNode:(id)node { + NSUInteger estimatedSize = + [FSnapshotUtilities estimateSerializedNodeSize:node]; + + // Splits for + // 1k -> 512 (2 parts) + // 5k -> 715 (7 parts) + // 100k -> 3.2k (32 parts) + // 500k -> 7k (71 parts) + // 5M -> 23k (228 parts) + NSUInteger splitThreshold = MAX(512, (NSUInteger)sqrt(estimatedSize * 100)); + + return ^BOOL(FCompoundHashBuilder *builder) { + // Never split on priorities + return [builder currentHashLength] > splitThreshold && + ![[[builder currentPath] getBack] isEqualToString:@".priority"]; + }; +} + ++ (FCompoundHash *)fromNode:(id)node { + return [FCompoundHash + fromNode:node + splitStrategy:[FCompoundHash simpleSizeSplitStrategyForNode:node]]; +} + ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy { + if ([node isEmpty]) { + return [[FCompoundHash alloc] initWithPosts:@[] hashes:@[ @"" ]]; + } else { + FCompoundHashBuilder *builder = + [[FCompoundHashBuilder alloc] initWithSplitStrategy:strategy]; + [FCompoundHash processNode:node builder:builder]; + [builder finishHashing]; + return [[FCompoundHash alloc] initWithPosts:builder.currentPaths + hashes:builder.currentHashes]; + } +} + ++ (void)processNode:(id)node builder:(FCompoundHashBuilder *)builder { + if ([node isLeafNode]) { + [builder processLeaf:node]; + } else { + NSAssert(![node isEmpty], @"Can't calculate hash on empty node!"); + FChildrenNode *childrenNode = (FChildrenNode *)node; + [childrenNode enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [builder startChild:key]; + [self processNode:node builder:builder]; + [builder endChild]; + }]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h new file mode 100644 index 00000000..8efd803a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" + +@class FQuerySpec; +@protocol FSyncTreeHash; + +typedef NSArray * (^fbt_startListeningBlock)(FQuerySpec *query, NSNumber *tagId, + id hash, + fbt_nsarray_nsstring onComplete); +typedef void (^fbt_stopListeningBlock)(FQuerySpec *query, NSNumber *tagId); + +@interface FListenProvider : NSObject + +@property(nonatomic, copy) fbt_startListeningBlock startListening; +@property(nonatomic, copy) fbt_stopListeningBlock stopListening; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m new file mode 100644 index 00000000..27da015c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenProvider.h" +#import "FIRDatabaseQuery.h" + +@implementation FListenProvider + +@synthesize startListening; +@synthesize stopListening; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h new file mode 100644 index 00000000..81836fd0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FRepoInfo.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@protocol FPersistentConnectionDelegate; +@protocol FSyncTreeHash; +@class FQuerySpec; +@class FIRDatabaseConfig; + +@interface FPersistentConnection : NSObject + +@property(nonatomic, weak) id delegate; +@property(nonatomic) BOOL pauseWrites; + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)queue + config:(FIRDatabaseConfig *)config; + +- (void)open; + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete; +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete; + +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete; + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId; +- (void)refreshAuthToken:(NSString *)token; +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)ackPuts; +- (void)purgeOutstandingWrites; + +- (void)interruptForReason:(NSString *)reason; +- (void)resumeForReason:(NSString *)reason; +- (BOOL)isInterruptedForReason:(NSString *)reason; + +// FConnection delegate methods +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +// Testing methods +- (NSDictionary *)dumpListens; + +@end + +@protocol FPersistentConnectionDelegate + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)path + tagId:(NSNumber *)tag; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m new file mode 100644 index 00000000..4a7b9e3c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m @@ -0,0 +1,1142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FAtomicNumber.h" +#import "FAuthTokenProvider.h" +#import "FCompoundHash.h" +#import "FConstants.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseReference.h" +#import "FIRRetryHelper.h" +#import "FIndex.h" +#import "FPersistentConnection.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTupleCallbackStatus.h" +#import "FTupleOnDisconnect.h" +#import "FUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import +#import +#import + +@interface FOutstandingQuery : NSObject + +@property(nonatomic, strong) FQuerySpec *query; +@property(nonatomic, strong) NSNumber *tagId; +@property(nonatomic, strong) id syncTreeHash; +@property(nonatomic, copy) fbt_void_nsstring onComplete; + +@end + +@implementation FOutstandingQuery + +@end + +@interface FOutstandingPut : NSObject + +@property(nonatomic, strong) NSString *action; +@property(nonatomic, strong) NSDictionary *request; +@property(nonatomic, copy) fbt_void_nsstring_nsstring onCompleteBlock; +@property(nonatomic) BOOL sent; + +@end + +@implementation FOutstandingPut + +@end + +typedef enum { + ConnectionStateDisconnected, + ConnectionStateGettingToken, + ConnectionStateConnecting, + ConnectionStateAuthenticating, + ConnectionStateConnected +} ConnectionState; + +@interface FPersistentConnection () { + ConnectionState connectionState; + BOOL firstConnection; + NSTimeInterval reconnectDelay; + NSTimeInterval lastConnectionAttemptTime; + NSTimeInterval lastConnectionEstablishedTime; + SCNetworkReachabilityRef reachability; +} + +- (int)getNextRequestNumber; +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body; +- (void)handleTimestamp:(NSNumber *)timestamp; +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback; + +@property(nonatomic, strong) FConnection *realtime; +@property(nonatomic, strong) NSMutableDictionary *listens; +@property(nonatomic, strong) NSMutableDictionary *outstandingPuts; +@property(nonatomic, strong) NSMutableArray *onDisconnectQueue; +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FAtomicNumber *putCounter; +@property(nonatomic, strong) FAtomicNumber *requestNumber; +@property(nonatomic, strong) NSMutableDictionary *requestCBHash; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic) NSUInteger unackedListensCount; +@property(nonatomic, strong) NSMutableArray *putsToAck; +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic, strong) NSString *lastSessionID; +@property(nonatomic, strong) NSMutableSet *interruptReasons; +@property(nonatomic, strong) FIRRetryHelper *retryHelper; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) NSString *authToken; +@property(nonatomic) BOOL forceAuthTokenRefresh; +@property(nonatomic) NSUInteger currentFetchTokenAttempt; + +@end + +@implementation FPersistentConnection + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)dispatchQueue + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self) { + self->_config = config; + self->_repoInfo = repoInfo; + self->_dispatchQueue = dispatchQueue; + self->_authTokenProvider = config.authTokenProvider; + NSAssert(self->_authTokenProvider != nil, + @"Expected auth token provider"); + self.interruptReasons = [NSMutableSet set]; + + self.listens = [[NSMutableDictionary alloc] init]; + self.outstandingPuts = [[NSMutableDictionary alloc] init]; + self.onDisconnectQueue = [[NSMutableArray alloc] init]; + self.putCounter = [[FAtomicNumber alloc] init]; + self.requestNumber = [[FAtomicNumber alloc] init]; + self.requestCBHash = [[NSMutableDictionary alloc] init]; + self.unackedListensCount = 0; + self.putsToAck = [NSMutableArray array]; + connectionState = ConnectionStateDisconnected; + firstConnection = YES; + reconnectDelay = kPersistentConnReconnectMinDelay; + + self->_retryHelper = [[FIRRetryHelper alloc] + initWithDispatchQueue:dispatchQueue + minRetryDelayAfterFailure:kPersistentConnReconnectMinDelay + maxRetryDelay:kPersistentConnReconnectMaxDelay + retryExponent:kPersistentConnReconnectMultiplier + jitterFactor:0.7]; + + [self setupNotifications]; + // Make sure we don't actually connect until open is called + [self interruptForReason:kFInterruptReasonWaitingForOpen]; + } + // nb: The reason establishConnection isn't called here like the JS version + // is because callers need to set the delegate first. The ctor can be + // modified to accept the delegate but that deviates from normal ios + // conventions. After the delegate has been set, the caller is responsible + // for calling establishConnection: + return self; +} + +- (void)dealloc { + if (reachability) { + // Unschedule the notifications + SCNetworkReachabilitySetDispatchQueue(reachability, NULL); + CFRelease(reachability); + } +} + +#pragma mark - +#pragma mark Public methods + +- (void)open { + [self resumeForReason:kFInterruptReasonWaitingForOpen]; +} + +/** + * Note that the listens dictionary has a type of Map[String (pathString), + * Map[FQueryParams, FOutstandingQuery]] + * + * This means, for each path we care about, there are sets of queryParams that + * correspond to an FOutstandingQuery object. There can be multiple sets at a + * path since we overlap listens for a short time while adding or removing a + * query from a location in the tree. + */ +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete { + FFLog(@"I-RDB034001", @"Listen called for %@", query); + + NSAssert(self.listens[query] == nil, + @"listen() called twice for the same query"); + NSAssert(query.isDefault || !query.loadsAllData, + @"listen called for non-default but complete query"); + FOutstandingQuery *outstanding = [[FOutstandingQuery alloc] init]; + outstanding.query = query; + outstanding.tagId = tagId; + outstanding.syncTreeHash = hash; + outstanding.onComplete = onComplete; + [self.listens setObject:outstanding forKey:query]; + if ([self connected]) { + [self sendListen:outstanding]; + } +} + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionPut + forPath:pathString + withHash:hash + withCallback:onComplete]; +} + +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionMerge + forPath:pathString + withHash:nil + withCallback:onComplete]; +} + +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectPut + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectPut; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectMerge + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectMerge; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectCancel + forPath:[path description] + withData:[NSNull null] + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectCancel; + tuple.data = [NSNull null]; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId { + FPath *path = query.path; + FFLog(@"I-RDB034002", @"Unlistening for %@", query); + + NSArray *outstanding = [self removeListen:query]; + if (outstanding.count > 0 && [self connected]) { + [self sendUnlisten:path queryParams:query.params tagId:tagId]; + } +} + +- (void)refreshAuthToken:(NSString *)token { + self.authToken = token; + if ([self connected]) { + if (token != nil) { + [self sendAuthAndRestoreStateAfterComplete:NO]; + } else { + [self sendUnauth]; + } + } +} + +#pragma mark - +#pragma mark Connection status + +- (BOOL)connected { + return self->connectionState == ConnectionStateAuthenticating || + self->connectionState == ConnectionStateConnected; +} + +- (BOOL)canSendWrites { + return self->connectionState == ConnectionStateConnected; +} + +#pragma mark - +#pragma mark FConnection delegate methods + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB034003", @"On ready"); + lastConnectionEstablishedTime = [[NSDate date] timeIntervalSince1970]; + [self handleTimestamp:timestamp]; + + if (firstConnection) { + [self sendConnectStats]; + } + + [self restoreAuth]; + firstConnection = NO; + self.lastSessionID = sessionID; + dispatch_async(self.dispatchQueue, ^{ + [self.delegate onConnect:self]; + }); +} + +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message { + if (message[kFWPRequestNumber] != nil) { + // this is a response to a request we sent + NSNumber *rn = [NSNumber + numberWithInt:[[message objectForKey:kFWPRequestNumber] intValue]]; + if ([self.requestCBHash objectForKey:rn]) { + void (^callback)(NSDictionary *) = + [self.requestCBHash objectForKey:rn]; + [self.requestCBHash removeObjectForKey:rn]; + + if (callback) { + // dispatch_async(self.dispatchQueue, ^{ + callback([message objectForKey:kFWPResponseForRNData]); + //}); + } + } + } else if (message[kFWPRequestError] != nil) { + NSString *error = [message objectForKey:kFWPRequestError]; + @throw [[NSException alloc] initWithName:@"FirebaseDatabaseServerError" + reason:error + userInfo:nil]; + } else if (message[kFWPAsyncServerAction] != nil) { + // this is a server push of some sort + NSString *action = [message objectForKey:kFWPAsyncServerAction]; + NSDictionary *body = [message objectForKey:kFWPAsyncServerPayloadBody]; + [self onDataPushWithAction:action andBody:body]; + } +} + +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason { + FFLog(@"I-RDB034004", @"Got on disconnect due to %s", + (reason == DISCONNECT_REASON_SERVER_RESET) ? "server_reset" + : "other"); + connectionState = ConnectionStateDisconnected; + // Drop the realtime connection + self.realtime = nil; + [self cancelSentTransactions]; + [self.requestCBHash removeAllObjects]; + self.unackedListensCount = 0; + if ([self shouldReconnect]) { + NSTimeInterval timeSinceLastConnectSucceeded = + [[NSDate date] timeIntervalSince1970] - + lastConnectionEstablishedTime; + BOOL lastConnectionWasSuccessful; + if (lastConnectionEstablishedTime > 0) { + lastConnectionWasSuccessful = + timeSinceLastConnectSucceeded > + kPersistentConnSuccessfulConnectionEstablishedDelay; + } else { + lastConnectionWasSuccessful = NO; + } + + if (reason == DISCONNECT_REASON_SERVER_RESET || + lastConnectionWasSuccessful) { + [self.retryHelper signalSuccess]; + } + [self tryScheduleReconnect]; + } + lastConnectionEstablishedTime = 0; + [self.delegate onDisconnect:self]; +} + +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason { + FFWarn(@"I-RDB034005", + @"Firebase Database connection was forcefully killed by the server. " + @" Will not attempt reconnect. Reason: %@", + reason); + [self interruptForReason:kFInterruptReasonServerKill]; +} + +#pragma mark - +#pragma mark Connection handling methods + +- (void)interruptForReason:(NSString *)reason { + FFLog(@"I-RDB034006", @"Connection interrupted for: %@", reason); + + [self.interruptReasons addObject:reason]; + if (self.realtime) { + // Will call onDisconnect and set the connection state to Disconnected + [self.realtime close]; + self.realtime = nil; + } else { + [self.retryHelper cancel]; + self->connectionState = ConnectionStateDisconnected; + } + // Reset timeouts + [self.retryHelper signalSuccess]; +} + +- (void)resumeForReason:(NSString *)reason { + FFLog(@"I-RDB034007", @"Connection no longer interrupted for: %@", reason); + [self.interruptReasons removeObject:reason]; + + if ([self shouldReconnect] && + connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } +} + +- (BOOL)shouldReconnect { + return self.interruptReasons.count == 0; +} + +- (BOOL)isInterruptedForReason:(NSString *)reason { + return [self.interruptReasons containsObject:reason]; +} + +#pragma mark - +#pragma mark Private methods + +- (void)tryScheduleReconnect { + if ([self shouldReconnect]) { + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + BOOL forceRefresh = self.forceAuthTokenRefresh; + self.forceAuthTokenRefresh = NO; + FFLog(@"I-RDB034008", @"Scheduling connection attempt"); + [self.retryHelper retry:^{ + FFLog(@"I-RDB034009", @"Trying to fetch auth token"); + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + self->connectionState = ConnectionStateGettingToken; + self.currentFetchTokenAttempt++; + NSUInteger thisFetchTokenAttempt = self.currentFetchTokenAttempt; + [self.authTokenProvider + fetchTokenForcingRefresh:forceRefresh + withCallback:^(NSString *token, NSError *error) { + if (thisFetchTokenAttempt == + self.currentFetchTokenAttempt) { + if (error != nil) { + self->connectionState = + ConnectionStateDisconnected; + FFLog(@"I-RDB034010", + @"Error fetching token: %@", error); + [self tryScheduleReconnect]; + } else { + // Someone could have interrupted us while + // fetching the token, marking the + // connection as Disconnected + if (self->connectionState == + ConnectionStateGettingToken) { + FFLog(@"I-RDB034011", + @"Successfully fetched token, " + @"opening connection"); + [self openNetworkConnectionWithToken: + token]; + } else { + NSAssert( + self->connectionState == + ConnectionStateDisconnected, + @"Expected connection state " + @"disconnected, but got %d", + self->connectionState); + FFLog(@"I-RDB034012", + @"Not opening connection after " + @"token refresh, because " + @"connection was set to " + @"disconnected."); + } + } + } else { + FFLog(@"I-RDB034013", + @"Ignoring fetch token result, because " + @"this was not the latest attempt."); + } + }]; + }]; + } +} + +- (void)openNetworkConnectionWithToken:(NSString *)token { + NSAssert(self->connectionState == ConnectionStateGettingToken, + @"Trying to open network connection while in wrong state: %d", + self->connectionState); + self.authToken = token; + self->connectionState = ConnectionStateConnecting; + self.realtime = [[FConnection alloc] initWith:self.repoInfo + andDispatchQueue:self.dispatchQueue + googleAppID:self.config.googleAppID + lastSessionID:self.lastSessionID]; + self.realtime.delegate = self; + [self.realtime open]; +} + +static void reachabilityCallback(SCNetworkReachabilityRef ref, + SCNetworkReachabilityFlags flags, void *info) { + if (flags & kSCNetworkReachabilityFlagsReachable) { + FFLog(@"I-RDB034014", + @"Network became reachable. Trigger a connection attempt"); + FPersistentConnection *self = (__bridge FPersistentConnection *)info; + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + } else { + FFLog(@"I-RDB034015", @"Network is not reachable"); + } +} + +- (void)enteringForeground { + dispatch_async(self.dispatchQueue, ^{ + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + }); +} + +- (void)setupNotifications { + + NSString *const *foregroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationWillEnterForegroundNotification"); + if (foregroundConstant) { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(enteringForeground) + name:*foregroundConstant + object:nil]; + } + // An empty address is interpreted a generic internet access + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + reachability = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + SCNetworkReachabilityContext ctx = {0, (__bridge void *)(self), NULL, NULL, + NULL}; + if (SCNetworkReachabilitySetCallback(reachability, reachabilityCallback, + &ctx)) { + SCNetworkReachabilitySetDispatchQueue(reachability, self.dispatchQueue); + } else { + FFLog(@"I-RDB034016", + @"Failed to set up network reachability monitoring"); + CFRelease(reachability); + reachability = NULL; + } +} + +- (void)sendAuthAndRestoreStateAfterComplete:(BOOL)restoreStateAfterComplete { + NSAssert([self connected], @"Must be connected to send auth"); + NSAssert(self.authToken != nil, + @"Can't send auth if there is no credential"); + + NSDictionary *requestData = @{kFWPRequestCredential : self.authToken}; + [self sendAction:kFWPRequestActionAuth + body:requestData + sensitive:YES + callback:^(NSDictionary *data) { + self->connectionState = ConnectionStateConnected; + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + id responseData = [data objectForKey:kFWPResponseForActionData]; + if (responseData == nil) { + responseData = @"error"; + } + + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (statusOk) { + if (restoreStateAfterComplete) { + [self restoreState]; + } + } else { + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034017", @"Authentication failed: %@ (%@)", + status, responseData); + } else { + FFWarn(@"I-RDB034018", @"Authentication failed: %@ (%@)", + status, responseData); + } + [self.realtime close]; + } + }]; +} + +- (void)sendUnauth { + [self sendAction:kFWPRequestActionUnauth + body:@{} + sensitive:NO + callback:nil]; +} + +- (void)onAuthRevokedWithStatus:(NSString *)status + andReason:(NSString *)reason { + // This might be for an earlier token than we just recently sent. But since + // we need to close the connection anyways, we can set it to null here and + // we will refresh the token later on reconnect + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034019", @"Auth token revoked: %@ (%@)", status, reason); + } else { + FFWarn(@"I-RDB034020", @"Auth token revoked: %@ (%@)", status, reason); + } + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + // Try reconnecting on auth revocation + [self.realtime close]; +} + +- (void)onListenRevoked:(FPath *)path { + NSArray *queries = [self removeAllListensAtPath:path]; + for (FOutstandingQuery *query in queries) { + query.onComplete(@"permission_denied"); + } +} + +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback { + + NSDictionary *request = + @{kFWPRequestPath : pathString, kFWPRequestData : data}; + FFLog(@"I-RDB034021", @"onDisconnect %@: %@", action, request); + + [self sendAction:action + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + callback(status, errorReason); + }]; +} + +- (void)sendPut:(NSNumber *)index { + NSAssert([self canSendWrites], + @"sendPut called when not able to send writes"); + FOutstandingPut *put = self.outstandingPuts[index]; + assert(put != nil); + fbt_void_nsstring_nsstring onComplete = put.onCompleteBlock; + + // Do not async this block; copying the block insinde sendAction: doesn't + // happen in time (or something) so coredumps + put.sent = YES; + [self sendAction:put.action + body:put.request + sensitive:NO + callback:^(NSDictionary *data) { + FOutstandingPut *currentPut = self.outstandingPuts[index]; + if (currentPut == put) { + [self.outstandingPuts removeObjectForKey:index]; + + if (onComplete != nil) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + if (self.unackedListensCount == 0) { + onComplete(status, errorReason); + } else { + FTupleCallbackStatus *putToAck = + [[FTupleCallbackStatus alloc] init]; + putToAck.block = onComplete; + putToAck.status = status; + putToAck.errorReason = errorReason; + [self.putsToAck addObject:putToAck]; + } + } + } else { + FFLog(@"I-RDB034022", + @"Ignoring on complete for put %@ because it was " + @"already removed", + index); + } + }]; +} + +- (void)sendUnlisten:(FPath *)path + queryParams:(FQueryParams *)queryParams + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB034023", @"Unlisten on %@ for %@", path, queryParams); + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:[path toString], kFWPRequestPath, nil]; + if (tagId != nil) { + [request setObject:queryParams.wireProtocolParams + forKey:kFWPRequestQueries]; + [request setObject:tagId forKey:kFWPRequestTag]; + } + + [self sendAction:kFWPRequestActionTaggedUnlisten + body:request + sensitive:NO + callback:nil]; +} + +- (void)putInternal:(id)data + forAction:(NSString *)action + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:pathString, kFWPRequestPath, data, + kFWPRequestData, nil]; + if (hash) { + [request setObject:hash forKey:kFWPRequestHash]; + } + + FOutstandingPut *put = [[FOutstandingPut alloc] init]; + put.action = action; + put.request = request; + put.onCompleteBlock = onComplete; + put.sent = NO; + + NSNumber *index = [self.putCounter getAndIncrement]; + self.outstandingPuts[index] = put; + + if ([self canSendWrites]) { + FFLog(@"I-RDB034024", @"Was connected, and added as index: %@", index); + [self sendPut:index]; + } else { + FFLog(@"I-RDB034025", + @"Wasn't connected or writes paused, so added to outstanding " + @"puts only. Path: %@", + pathString); + } +} + +- (void)sendListen:(FOutstandingQuery *)listenSpec { + FQuerySpec *query = listenSpec.query; + FFLog(@"I-RDB034026", @"Listen for %@", query); + NSMutableDictionary *request = + [NSMutableDictionary dictionaryWithObject:[query.path toString] + forKey:kFWPRequestPath]; + + // Only bother to send query if it's non-default + if (listenSpec.tagId != nil) { + [request setObject:[query.params wireProtocolParams] + forKey:kFWPRequestQueries]; + [request setObject:listenSpec.tagId forKey:kFWPRequestTag]; + } + + [request setObject:[listenSpec.syncTreeHash simpleHash] + forKey:kFWPRequestHash]; + if ([listenSpec.syncTreeHash includeCompoundHash]) { + FCompoundHash *compoundHash = [listenSpec.syncTreeHash compoundHash]; + NSMutableArray *posts = [NSMutableArray array]; + for (FPath *path in compoundHash.posts) { + [posts addObject:path.wireFormat]; + } + request[kFWPRequestCompoundHash] = @{ + kFWPRequestCompoundHashHashes : compoundHash.hashes, + kFWPRequestCompoundHashPaths : posts + }; + } + + fbt_void_nsdictionary onResponse = ^(NSDictionary *response) { + FFLog(@"I-RDB034027", @"Listen response %@", response); + // warn in any case, even if the listener was removed + [self warnOnListenWarningsForQuery:query + payload:response[kFWPResponseForActionData]]; + + FOutstandingQuery *currentListenSpec = self.listens[query]; + + // only trigger actions if the listen hasn't been removed (and maybe + // readded) + if (currentListenSpec == listenSpec) { + NSString *status = [response objectForKey:kFWPRequestStatus]; + if (![status isEqualToString:@"ok"]) { + [self removeListen:query]; + } + + if (listenSpec.onComplete) { + listenSpec.onComplete(status); + } + } + + self.unackedListensCount--; + NSAssert(self.unackedListensCount >= 0, + @"unackedListensCount decremented to be negative."); + if (self.unackedListensCount == 0) { + [self ackPuts]; + } + }; + + [self sendAction:kFWPRequestActionTaggedListen + body:request + sensitive:NO + callback:onResponse]; + + self.unackedListensCount++; +} + +- (void)warnOnListenWarningsForQuery:(FQuerySpec *)query payload:(id)payload { + if (payload != nil && [payload isKindOfClass:[NSDictionary class]]) { + NSDictionary *payloadDict = payload; + id warnings = payloadDict[kFWPResponseDataWarnings]; + if (warnings != nil && [warnings isKindOfClass:[NSArray class]]) { + NSArray *warningsArr = warnings; + if ([warningsArr containsObject:@"no_index"]) { + NSString *indexSpec = [NSString + stringWithFormat:@"\".indexOn\": \"%@\"", + [query.params.index queryDefinition]]; + NSString *indexPath = [query.path description]; + FFWarn(@"I-RDB034028", + @"Using an unspecified index. Your data will be " + @"downloaded and filtered on the client. " + "Consider adding %@ at %@ to your security rules for " + "better performance", + indexSpec, indexPath); + } + } + } +} + +- (int)getNextRequestNumber { + return [[self.requestNumber getAndIncrement] intValue]; +} + +- (void)sendAction:(NSString *)action + body:(NSDictionary *)message + sensitive:(BOOL)sensitive + callback:(void (^)(NSDictionary *data))onMessage { + // Hold onto the onMessage callback for this request before firing it off + NSNumber *rn = [NSNumber numberWithInt:[self getNextRequestNumber]]; + NSDictionary *msg = [NSDictionary + dictionaryWithObjectsAndKeys:rn, kFWPRequestNumber, action, + kFWPRequestAction, message, + kFWPRequestPayloadBody, nil]; + + [self.realtime sendRequest:msg sensitive:sensitive]; + + if (onMessage) { + // Debug message without a callback; bump the rn, but don't hold onto + // the cb + [self.requestCBHash setObject:[onMessage copy] forKey:rn]; + } +} + +- (void)cancelSentTransactions { + NSMutableDictionary + *cancelledOutstandingPuts = [[NSMutableDictionary alloc] init]; + + for (NSNumber *index in self.outstandingPuts) { + FOutstandingPut *put = self.outstandingPuts[index]; + if (put.request[kFWPRequestHash] && put.sent) { + // This is a sent transaction put. + cancelledOutstandingPuts[index] = put; + } + } + + [cancelledOutstandingPuts + enumerateKeysAndObjectsUsingBlock:^( + NSNumber *index, FOutstandingPut *outstandingPut, BOOL *stop) { + // `onCompleteBlock:` may invoke `rerunTransactionsForPath:` and + // enqueue new writes. We defer calling it until we have finished + // enumerating all existing writes. + outstandingPut.onCompleteBlock( + kFTransactionDisconnect, + @"Client was disconnected while running a transaction"); + [self.outstandingPuts removeObjectForKey:index]; + }]; +} + +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body { + FFLog(@"I-RDB034029", @"handleServerMessage: %@, %@", action, body); + id delegate = self.delegate; + if ([action isEqualToString:kFWPAsyncServerDataUpdate] || + [action isEqualToString:kFWPAsyncServerDataMerge]) { + BOOL isMerge = [action isEqualToString:kFWPAsyncServerDataMerge]; + + if ([body objectForKey:kFWPAsyncServerDataUpdateBodyPath] && + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]) { + NSString *path = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + id payloadData = + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]; + if (isMerge && [payloadData isKindOfClass:[NSDictionary class]] && + [payloadData count] == 0) { + // ignore empty merge + } else { + [delegate + onDataUpdate:self + forPath:path + message:payloadData + isMerge:isMerge + tagId:[body objectForKey: + kFWPAsyncServerDataUpdateBodyTag]]; + } + } else { + FFLog( + @"I-RDB034030", + @"Malformed data response from server missing path or data: %@", + body); + } + } else if ([action isEqualToString:kFWPAsyncServerDataRangeMerge]) { + NSString *path = body[kFWPAsyncServerDataUpdateBodyPath]; + NSArray *ranges = body[kFWPAsyncServerDataUpdateBodyData]; + NSNumber *tag = body[kFWPAsyncServerDataUpdateBodyTag]; + NSMutableArray *rangeMerges = [NSMutableArray array]; + for (NSDictionary *range in ranges) { + NSString *startString = range[kFWPAsyncServerDataUpdateStartPath]; + NSString *endString = range[kFWPAsyncServerDataUpdateEndPath]; + id updateData = range[kFWPAsyncServerDataUpdateRangeMerge]; + id updates = [FSnapshotUtilities nodeFrom:updateData]; + FPath *start = (startString != nil) + ? [[FPath alloc] initWith:startString] + : nil; + FPath *end = + (endString != nil) ? [[FPath alloc] initWith:endString] : nil; + FRangeMerge *merge = [[FRangeMerge alloc] initWithStart:start + end:end + updates:updates]; + [rangeMerges addObject:merge]; + } + [delegate onRangeMerge:rangeMerges forPath:path tagId:tag]; + } else if ([action isEqualToString:kFWPAsyncServerAuthRevoked]) { + NSString *status = [body objectForKey:kFWPResponseForActionStatus]; + NSString *reason = [body objectForKey:kFWPResponseForActionData]; + [self onAuthRevokedWithStatus:status andReason:reason]; + } else if ([action isEqualToString:kFWPASyncServerListenCancelled]) { + NSString *pathString = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + [self onListenRevoked:[[FPath alloc] initWith:pathString]]; + } else if ([action isEqualToString:kFWPAsyncServerSecurityDebug]) { + NSString *msg = [body objectForKey:@"msg"]; + if (msg != nil) { + NSArray *msgs = [msg componentsSeparatedByString:@"\n"]; + for (NSString *m in msgs) { + FFWarn(@"I-RDB034031", @"%@", m); + } + } + } else { + // TODO: revoke listens, auth, security debug + FFLog(@"I-RDB034032", @"Unsupported action from server: %@", action); + } +} + +- (void)restoreAuth { + FFLog(@"I-RDB034033", @"Calling restore state"); + + NSAssert(self->connectionState == ConnectionStateConnecting, + @"Wanted to restore auth, but was in wrong state: %d", + self->connectionState); + if (self.authToken == nil) { + FFLog(@"I-RDB034034", @"Not restoring auth because token is nil"); + self->connectionState = ConnectionStateConnected; + [self restoreState]; + } else { + FFLog(@"I-RDB034035", @"Restoring auth"); + self->connectionState = ConnectionStateAuthenticating; + [self sendAuthAndRestoreStateAfterComplete:YES]; + } +} + +- (void)restoreState { + NSAssert(self->connectionState == ConnectionStateConnected, + @"Should be connected if we're restoring state, but we are: %d", + self->connectionState); + + [self.listens enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *query, FOutstandingQuery *outstandingListen, + BOOL *stop) { + FFLog(@"I-RDB034036", @"Restoring listen for %@", query); + [self sendListen:outstandingListen]; + }]; + + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (int i = 0; i < [keys count]; i++) { + if ([self.outstandingPuts objectForKey:[keys objectAtIndex:i]] != nil) { + FFLog(@"I-RDB034037", @"Restoring put: %d", i); + [self sendPut:[keys objectAtIndex:i]]; + } else { + FFLog(@"I-RDB034038", @"Restoring put: skipped nil: %d", i); + } + } + + for (FTupleOnDisconnect *tuple in self.onDisconnectQueue) { + [self sendOnDisconnectAction:tuple.action + forPath:tuple.pathString + withData:tuple.data + andCallback:tuple.onComplete]; + } + [self.onDisconnectQueue removeAllObjects]; +} + +- (NSArray *)removeListen:(FQuerySpec *)query { + NSAssert(query.isDefault || !query.loadsAllData, + @"removeListen called for non-default but complete query"); + + FOutstandingQuery *outstanding = self.listens[query]; + if (!outstanding) { + FFLog(@"I-RDB034039", + @"Trying to remove listener for query %@ but no listener exists", + query); + return @[]; + } else { + [self.listens removeObjectForKey:query]; + return @[ outstanding ]; + } +} + +- (NSArray *)removeAllListensAtPath:(FPath *)path { + FFLog(@"I-RDB034040", @"Removing all listens at path %@", path); + NSMutableArray *removed = [NSMutableArray array]; + NSMutableArray *toRemove = [NSMutableArray array]; + [self.listens + enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *spec, FOutstandingQuery *outstanding, BOOL *stop) { + if ([spec.path isEqual:path]) { + [removed addObject:outstanding]; + [toRemove addObject:spec]; + } + }]; + [self.listens removeObjectsForKeys:toRemove]; + return removed; +} + +- (void)purgeOutstandingWrites { + // We might have unacked puts in our queue that we need to ack now before we + // send out any cancels... + [self ackPuts]; + // Cancel in order + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (NSNumber *key in keys) { + FOutstandingPut *put = self.outstandingPuts[key]; + if (put.onCompleteBlock != nil) { + put.onCompleteBlock(kFErrorWriteCanceled, nil); + } + } + for (FTupleOnDisconnect *onDisconnect in self.onDisconnectQueue) { + if (onDisconnect.onComplete != nil) { + onDisconnect.onComplete(kFErrorWriteCanceled, nil); + } + } + [self.outstandingPuts removeAllObjects]; + [self.onDisconnectQueue removeAllObjects]; +} + +- (void)ackPuts { + for (FTupleCallbackStatus *put in self.putsToAck) { + put.block(put.status, put.errorReason); + } + [self.putsToAck removeAllObjects]; +} + +- (void)handleTimestamp:(NSNumber *)timestamp { + FFLog(@"I-RDB034041", @"Handling timestamp: %@", timestamp); + double timestampDeltaMs = [timestamp doubleValue] - + ([[NSDate date] timeIntervalSince1970] * 1000); + [self.delegate onServerInfoUpdate:self + updates:@{ + kDotInfoServerTimeOffset : [NSNumber + numberWithDouble:timestampDeltaMs] + }]; +} + +- (void)sendStats:(NSDictionary *)stats { + if ([stats count] > 0) { + NSDictionary *request = @{kFWPRequestCounters : stats}; + [self sendAction:kFWPRequestActionStats + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (!statusOk) { + FFLog(@"I-RDB034042", @"Failed to send stats: %@", + errorReason); + } + }]; + } else { + FFLog(@"I-RDB034043", @"Not sending stats because stats are empty"); + } +} + +- (void)sendConnectStats { + NSMutableDictionary *stats = [NSMutableDictionary dictionary]; + +#if TARGET_OS_IOS || TARGET_OS_TV + if (self.config.persistenceEnabled) { + stats[@"persistence.ios.enabled"] = @1; + } +#elif TARGET_OS_OSX + if (self.config.persistenceEnabled) { + stats[@"persistence.osx.enabled"] = @1; + } +#endif + NSString *sdkVersion = + [[FIRDatabase sdkVersion] stringByReplacingOccurrencesOfString:@"." + withString:@"-"]; + NSString *sdkStatName = + [NSString stringWithFormat:@"sdk.objc.%@", sdkVersion]; + stats[sdkStatName] = @1; + FFLog(@"I-RDB034044", @"Sending first connection stats"); + [self sendStats:stats]; +} + +- (NSDictionary *)dumpListens { + return self.listens; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h new file mode 100644 index 00000000..5d957c57 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FIndex +, FNodeFilter, FNode; + +@interface FQueryParams : NSObject + +@property(nonatomic, readonly) BOOL limitSet; +@property(nonatomic, readonly) NSInteger limit; + +@property(nonatomic, strong, readonly) NSString *viewFrom; +@property(nonatomic, strong, readonly) id indexStartValue; +@property(nonatomic, strong, readonly) NSString *indexStartKey; +@property(nonatomic, strong, readonly) id indexEndValue; +@property(nonatomic, strong, readonly) NSString *indexEndKey; + +@property(nonatomic, strong, readonly) id index; + +- (BOOL)loadsAllData; +- (BOOL)isDefault; +- (BOOL)isValid; +- (BOOL)hasAnchoredLimit; + +- (FQueryParams *)limitTo:(NSInteger)limit; +- (FQueryParams *)limitToFirst:(NSInteger)newLimit; +- (FQueryParams *)limitToLast:(NSInteger)newLimit; + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)startAt:(id)indexValue; +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)endAt:(id)indexValue; + +- (FQueryParams *)orderBy:(id)index; + ++ (FQueryParams *)defaultInstance; ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict; + +- (BOOL)hasStart; +- (BOOL)hasEnd; + +- (NSDictionary *)wireProtocolParams; +- (BOOL)isViewFromLeft; +- (id)nodeFilter; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m new file mode 100644 index 00000000..c19cfba2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m @@ -0,0 +1,393 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FConstants.h" +#import "FIndex.h" +#import "FIndexedFilter.h" +#import "FLimitedFilter.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FPriorityIndex.h" +#import "FRangedFilter.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" + +@interface FQueryParams () + +@property(nonatomic, readwrite) BOOL limitSet; +@property(nonatomic, readwrite) NSInteger limit; + +@property(nonatomic, strong, readwrite) NSString *viewFrom; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexStartValue; +@property(nonatomic, strong, readwrite) NSString *indexStartKey; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexEndValue; +@property(nonatomic, strong, readwrite) NSString *indexEndKey; + +@property(nonatomic, strong, readwrite) id index; + +@end + +@implementation FQueryParams + ++ (FQueryParams *)defaultInstance { + static FQueryParams *defaultParams = nil; + static dispatch_once_t defaultParamsToken; + dispatch_once(&defaultParamsToken, ^{ + defaultParams = [[FQueryParams alloc] init]; + }); + return defaultParams; +} + +- (id)init { + self = [super init]; + if (self) { + self->_limitSet = NO; + self->_limit = 0; + + self->_viewFrom = nil; + self->_indexStartValue = nil; + self->_indexStartKey = nil; + self->_indexEndValue = nil; + self->_indexEndKey = nil; + + self->_index = [FPriorityIndex priorityIndex]; + } + return self; +} + +/** + * Only valid if hasStart is true + */ +- (id)indexStartValue { + NSAssert([self hasStart], @"Only valid if start has been set"); + return _indexStartValue; +} + +/** + * Only valid if hasStart is true. + * @return The starting key name for the range defined by these query parameters + */ +- (NSString *)indexStartKey { + NSAssert([self hasStart], @"Only valid if start has been set"); + if (_indexStartKey == nil) { + return [FUtilities minName]; + } else { + return _indexStartKey; + } +} + +/** + * Only valid if hasEnd is true. + */ +- (id)indexEndValue { + NSAssert([self hasEnd], @"Only valid if end has been set"); + return _indexEndValue; +} + +/** + * Only valid if hasEnd is true. + * @return The end key name for the range defined by these query parameters + */ +- (NSString *)indexEndKey { + NSAssert([self hasEnd], @"Only valid if end has been set"); + if (_indexEndKey == nil) { + return [FUtilities maxName]; + } else { + return _indexEndKey; + } +} + +/** + * @return true if a limit has been set and has been explicitly anchored + */ +- (BOOL)hasAnchoredLimit { + return self.limitSet && self.viewFrom != nil; +} + +/** + * Only valid to call if limitSet returns true + */ +- (NSInteger)limit { + NSAssert(self.limitSet, @"Only valid if limit has been set"); + return _limit; +} + +- (BOOL)hasStart { + return self->_indexStartValue != nil; +} + +- (BOOL)hasEnd { + return self->_indexEndValue != nil; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)mutableCopy { + FQueryParams *other = [[[self class] alloc] init]; + // Maybe need to do extra copying here + other->_limitSet = _limitSet; + other->_limit = _limit; + other->_indexStartValue = _indexStartValue; + other->_indexStartKey = _indexStartKey; + other->_indexEndValue = _indexEndValue; + other->_indexEndKey = _indexEndKey; + other->_viewFrom = _viewFrom; + other->_index = _index; + return other; +} + +- (FQueryParams *)limitTo:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = nil; + return newParams; +} + +- (FQueryParams *)limitToFirst:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromLeft; + return newParams; +} + +- (FQueryParams *)limitToLast:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromRight; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexStartValue = indexValue; + newParams->_indexStartKey = key; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue { + return [self startAt:indexValue childKey:nil]; +} + +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexEndValue = indexValue; + newParams->_indexEndKey = key; + return newParams; +} + +- (FQueryParams *)endAt:(id)indexValue { + return [self endAt:indexValue childKey:nil]; +} + +- (FQueryParams *)orderBy:(id)newIndex { + FQueryParams *newParams = [self mutableCopy]; + newParams->_index = newIndex; + return newParams; +} + +- (NSDictionary *)wireProtocolParams { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + if ([self hasStart]) { + [dict setObject:[self.indexStartValue valForExport:YES] + forKey:kFQPIndexStartValue]; + + // Don't use property as it will be [MIN-NAME] + if (self->_indexStartKey != nil) { + [dict setObject:self->_indexStartKey forKey:kFQPIndexStartName]; + } + } + + if ([self hasEnd]) { + [dict setObject:[self.indexEndValue valForExport:YES] + forKey:kFQPIndexEndValue]; + + // Don't use property as it will be [MAX-NAME] + if (self->_indexEndKey != nil) { + [dict setObject:self->_indexEndKey forKey:kFQPIndexEndName]; + } + } + + if (self.limitSet) { + [dict setObject:[NSNumber numberWithInteger:self.limit] + forKey:kFQPLimit]; + NSString *vf = self.viewFrom; + if (vf == nil) { + // limit() rather than limitToFirst or limitToLast was called. + // This means that only one of startSet or endSet is true. Use them + // to calculate which side of the view to anchor to. If neither is + // set, Anchor to end + if ([self hasStart]) { + vf = kFQPViewFromLeft; + } else { + vf = kFQPViewFromRight; + } + } + [dict setObject:vf forKey:kFQPViewFrom]; + } + + // For now, priority index is the default, so we only specify if it's some + // other index. + if (![self.index isEqual:[FPriorityIndex priorityIndex]]) { + [dict setObject:[self.index queryDefinition] forKey:kFQPIndex]; + } + + return dict; +} + ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict { + if (dict.count == 0) { + return [FQueryParams defaultInstance]; + } + + FQueryParams *params = [[FQueryParams alloc] init]; + if (dict[kFQPLimit] != nil) { + params->_limitSet = YES; + params->_limit = [dict[kFQPLimit] integerValue]; + } + + if (dict[kFQPIndexStartValue] != nil) { + params->_indexStartValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexStartValue]]; + if (dict[kFQPIndexStartName] != nil) { + params->_indexStartKey = dict[kFQPIndexStartName]; + } + } + + if (dict[kFQPIndexEndValue] != nil) { + params->_indexEndValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexEndValue]]; + if (dict[kFQPIndexEndName] != nil) { + params->_indexEndKey = dict[kFQPIndexEndName]; + } + } + + if (dict[kFQPViewFrom] != nil) { + NSString *viewFrom = dict[kFQPViewFrom]; + if (![viewFrom isEqualToString:kFQPViewFromLeft] && + ![viewFrom isEqualToString:kFQPViewFromRight]) { + [NSException raise:NSInvalidArgumentException + format:@"Unknown view from paramter: %@", viewFrom]; + } + params->_viewFrom = viewFrom; + } + + NSString *index = dict[kFQPIndex]; + if (index != nil) { + params->_index = [FIndex indexFromQueryDefinition:index]; + } + + return params; +} + +- (BOOL)isViewFromLeft { + if (self.viewFrom != nil) { + // Not null, we can just check + return [self.viewFrom isEqualToString:kFQPViewFromLeft]; + } else { + // If start is set, it's view from left. Otherwise not. + return self.hasStart; + } +} + +- (id)nodeFilter { + if (self.loadsAllData) { + return [[FIndexedFilter alloc] initWithIndex:self.index]; + } else if (self.limitSet) { + return [[FLimitedFilter alloc] initWithQueryParams:self]; + } else { + return [[FRangedFilter alloc] initWithQueryParams:self]; + } +} + +- (BOOL)isValid { + return !(self.hasStart && self.hasEnd && self.limitSet && + !self.hasAnchoredLimit); +} + +- (BOOL)loadsAllData { + return !(self.hasStart || self.hasEnd || self.limitSet); +} + +- (BOOL)isDefault { + return [self loadsAllData] && + [self.index isEqual:[FPriorityIndex priorityIndex]]; +} + +- (NSString *)description { + return [[self wireProtocolParams] description]; +} + +- (BOOL)isEqual:(id)obj { + if (self == obj) { + return YES; + } + if (![obj isKindOfClass:[self class]]) { + return NO; + } + FQueryParams *other = (FQueryParams *)obj; + if (self->_limitSet != other->_limitSet) + return NO; + if (self->_limit != other->_limit) + return NO; + if ((self->_index != other->_index) && ! + [self->_index isEqual:other->_index]) + return NO; + if ((self->_indexStartKey != other->_indexStartKey) && + ![self->_indexStartKey isEqualToString:other->_indexStartKey]) + return NO; + if ((self->_indexStartValue != other->_indexStartValue) && + ![self->_indexStartValue isEqual:other->_indexStartValue]) + return NO; + if ((self->_indexEndKey != other->_indexEndKey) && + ![self->_indexEndKey isEqualToString:other->_indexEndKey]) + return NO; + if ((self->_indexEndValue != other->_indexEndValue) && + ![self->_indexEndValue isEqual:other->_indexEndValue]) + return NO; + if ([self isViewFromLeft] != [other isViewFromLeft]) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger result = _limitSet ? _limit : 0; + result = 31 * result + ([self isViewFromLeft] ? 1231 : 1237); + result = 31 * result + [_indexStartKey hash]; + result = 31 * result + [_indexStartValue hash]; + result = 31 * result + [_indexEndKey hash]; + result = 31 * result + [_indexEndValue hash]; + result = 31 * result + [_index hash]; + return result; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h new file mode 100644 index 00000000..2eece871 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FQuerySpec : NSObject + +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FQueryParams *params; + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params; + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path; + +- (id)index; +- (BOOL)isDefault; +- (BOOL)loadsAllData; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m new file mode 100644 index 00000000..c408bf8a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQuerySpec.h" + +@interface FQuerySpec () + +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) FQueryParams *params; + +@end + +@implementation FQuerySpec + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params { + self = [super init]; + if (self != nil) { + self->_path = path; + self->_params = params; + } + return self; +} + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path { + return [[FQuerySpec alloc] initWithPath:path + params:[FQueryParams defaultInstance]]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)index { + return self.params.index; +} + +- (BOOL)isDefault { + return self.params.isDefault; +} + +- (BOOL)loadsAllData { + return self.params.loadsAllData; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FQuerySpec class]]) { + return NO; + } + + FQuerySpec *other = (FQuerySpec *)object; + + if (![self.path isEqual:other.path]) { + return NO; + } + + return [self.params isEqual:other.params]; +} + +- (NSUInteger)hash { + return self.path.hash * 31 + self.params.hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FQuerySpec (path: %@, params: %@)", + self.path, self.params]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h new file mode 100644 index 00000000..5f7938a3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +/** + * Applies a merge of a snap for a given interval of paths. + * Each leaf in the current node which the relative path lies *after* (the + * optional) start and lies *before or at* (the optional) end will be deleted. + * Each leaf in snap that lies in the interval will be added to the resulting + * node. Nodes outside of the range are ignored. nil for start and end are + * sentinel values that represent -infinity and +infinity respectively (aka + * includes any path). Priorities of children nodes are treated as leaf children + * of that node. + */ +@interface FRangeMerge : NSObject + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates; + +- (id)applyToNode:(id)node; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m new file mode 100644 index 00000000..3dc1576c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m @@ -0,0 +1,134 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangeMerge.h" + +#import "FEmptyNode.h" + +@interface FRangeMerge () + +@property(nonatomic, strong) FPath *optExclusiveStart; +@property(nonatomic, strong) FPath *optInclusiveEnd; +@property(nonatomic, strong) id updates; + +@end + +@implementation FRangeMerge + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates { + self = [super init]; + if (self != nil) { + self->_optExclusiveStart = start; + self->_optInclusiveEnd = end; + self->_updates = updates; + } + return self; +} + +- (id)applyToNode:(id)node { + return [self updateRangeInNode:[FPath empty] + node:node + updates:self.updates]; +} + +- (id)updateRangeInNode:(FPath *)currentPath + node:(id)node + updates:(id)updates { + NSComparisonResult startComparison = + (self.optExclusiveStart == nil) + ? NSOrderedDescending + : [currentPath compare:self.optExclusiveStart]; + NSComparisonResult endComparison = + (self.optInclusiveEnd == nil) + ? NSOrderedAscending + : [currentPath compare:self.optInclusiveEnd]; + BOOL startInNode = self.optExclusiveStart != nil && + [currentPath contains:self.optExclusiveStart]; + BOOL endInNode = self.optInclusiveEnd != nil && + [currentPath contains:self.optInclusiveEnd]; + if (startComparison == NSOrderedDescending && + endComparison == NSOrderedAscending && !endInNode) { + // child is completly contained + return updates; + } else if (startComparison == NSOrderedDescending && endInNode && + [updates isLeafNode]) { + return updates; + } else if (startComparison == NSOrderedDescending && + endComparison == NSOrderedSame) { + NSAssert(endInNode, @"End not in node"); + NSAssert(![updates isLeafNode], @"Found leaf node update, this case " + @"should have been handled above."); + if ([node isLeafNode]) { + // Update node was not a leaf node, so we can delete it + return [FEmptyNode emptyNode]; + } else { + // Unaffected by range, ignore + return node; + } + } else if (startInNode || endInNode) { + // There is a partial update we need to do, so collect all relevant + // children + NSMutableSet *allChildren = [NSMutableSet set]; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + [updates enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + + __block id newNode = node; + void (^action)(id, BOOL *) = ^void(NSString *key, BOOL *stop) { + id currentChild = [node getImmediateChild:key]; + id updatedChild = + [self updateRangeInNode:[currentPath childFromString:key] + node:currentChild + updates:[updates getImmediateChild:key]]; + // Only need to update if the node changed + if (updatedChild != currentChild) { + newNode = [newNode updateImmediateChild:key + withNewChild:updatedChild]; + } + }; + + [allChildren enumerateObjectsUsingBlock:action]; + + // Add priority last, so the node is not empty when applying + if (!updates.getPriority.isEmpty || !node.getPriority.isEmpty) { + BOOL stop = NO; + action(@".priority", &stop); + } + return newNode; + } else { + // Unaffected by this range + NSAssert(endComparison == NSOrderedDescending || + startComparison <= NSOrderedSame, + @"Invalid range for update"); + return node; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"RangeMerge (optExclusiveStart = %@, " + @"optExclusiveEng = %@, updates = %@)", + self.optExclusiveStart, + self.optInclusiveEnd, self.updates]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h new file mode 100644 index 00000000..4e3899a6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h @@ -0,0 +1,93 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FPersistentConnection.h" +#import "FRepoInfo.h" +#import "FTupleUserCallback.h" +#import + +@class FQuerySpec; +@class FPersistence; +@class FAuthenticationManager; +@class FIRDatabaseConfig; +@protocol FEventRegistration; +@class FCompoundWrite; +@protocol FClock; +@class FIRDatabase; + +@interface FRepo : NSObject + +@property(nonatomic, strong) FIRDatabaseConfig *config; + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete; +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; +- (void)purgeOutstandingWrites; + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced; + +- (NSString *)name; +- (NSTimeInterval)serverTime; + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; + +// Disconnect methods +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; + +// Connection Management. +- (void)interrupt; +- (void)resume; + +// Transactions +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally; + +// Testing methods +- (NSDictionary *)dumpListens; +- (void)dispose; +- (void)setHijackHash:(BOOL)hijack; + +@property(nonatomic, strong, readonly) FAuthenticationManager *auth; +@property(nonatomic, strong, readonly) FIRDatabase *database; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m new file mode 100644 index 00000000..55086173 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m @@ -0,0 +1,1467 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FAtomicNumber.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FIRDataSnapshot.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FIRMutableData.h" +#import "FIRMutableData_Private.h" +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" +#import "FLevelDBStorageEngine.h" +#import "FListenProvider.h" +#import "FPersistenceManager.h" +#import "FQuerySpec.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FRepo_Private.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTree.h" +#import "FTupleNodePath.h" +#import "FTupleSetIdPath.h" +#import "FTupleTransaction.h" +#import "FValueEventRegistration.h" +#import "FWriteRecord.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FRepo () + +@property(nonatomic, strong) FOffsetClock *serverClock; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FIRDatabase *database; +@property(nonatomic, strong, readwrite) FAuthenticationManager *auth; +@property(nonatomic, strong) FSyncTree *infoSyncTree; +@property(nonatomic) NSInteger writeIdCounter; +@property(nonatomic) BOOL hijackHash; +@property(nonatomic, strong) FTree *transactionQueueTree; +@property(nonatomic) BOOL loggedTransactionPersistenceWarning; + +/** + * Test only. For load testing the server. + */ +@property(nonatomic, strong) id (^interceptServerDataCallback) + (NSString *pathString, id data); +@end + +@implementation FRepo + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + self = [super init]; + if (self) { + self.repoInfo = info; + self.config = config; + self.database = database; + + // Access can occur outside of shared queue, so the clock needs to be + // initialized here + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] offset:0]; + + self.connection = [[FPersistentConnection alloc] + initWithRepoInfo:self.repoInfo + dispatchQueue:[FIRDatabaseQuery sharedQueue] + config:self.config]; + + // Needs to be called before authentication manager is instantiated + self.eventRaiser = + [[FEventRaiser alloc] initWithQueue:self.config.callbackQueue]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self deferredInit]; + }); + } + return self; +} + +- (void)deferredInit { + // TODO: cleanup on dealloc + __weak FRepo *weakSelf = self; + [self.config.authTokenProvider listenForTokenChanges:^(NSString *token) { + [weakSelf.connection refreshAuthToken:token]; + }]; + + // Open connection now so that by the time we are connected the deferred + // init has run This relies on the fact that all callbacks run on repos + // queue + self.connection.delegate = self; + [self.connection open]; + + self.dataUpdateCount = 0; + self.rangeMergeUpdateCount = 0; + self.interceptServerDataCallback = nil; + + if (self.config.persistenceEnabled) { + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", self.repoInfo.host, + self.repoInfo.namespace]; + NSString *persistencePrefix = + [NSString stringWithFormat:@"%@/%@", self.config.sessionIdentifier, + repoHashString]; + + id cachePolicy = [[FLRUCachePolicy alloc] + initWithMaxSize:self.config.persistenceCacheSizeBytes]; + + id engine; + if (self.config.forceStorageEngine != nil) { + engine = self.config.forceStorageEngine; + } else { + FLevelDBStorageEngine *levelDBEngine = + [[FLevelDBStorageEngine alloc] initWithPath:persistencePrefix]; + // We need the repo info to run the legacy migration. Future + // migrations will be managed by the database itself Remove this + // once we are confident that no-one is using legacy migration + // anymore... + [levelDBEngine runLegacyMigration:self.repoInfo]; + engine = levelDBEngine; + } + + self.persistenceManager = + [[FPersistenceManager alloc] initWithStorageEngine:engine + cachePolicy:cachePolicy]; + } else { + self.persistenceManager = nil; + } + + [self initTransactions]; + + // A list of data pieces and paths to be set when this client disconnects + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + self.infoData = [[FSnapshotHolder alloc] init]; + + FListenProvider *infoListenProvider = [[FListenProvider alloc] init]; + infoListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + NSArray *infoEvents = @[]; + FRepo *strongSelf = weakSelf; + id node = [strongSelf.infoData getNode:query.path]; + // This is possibly a hack, but we have different semantics for .info + // endpoints. We don't raise null events on initial data... + if (![node isEmpty]) { + infoEvents = + [strongSelf.infoSyncTree applyServerOverwriteAtPath:query.path + newData:node]; + [strongSelf.eventRaiser raiseCallback:^{ + onComplete(kFWPResponseForActionStatusOk); + }]; + } + return infoEvents; + }; + infoListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tagId) { + }; + self.infoSyncTree = + [[FSyncTree alloc] initWithListenProvider:infoListenProvider]; + + FListenProvider *serverListenProvider = [[FListenProvider alloc] init]; + serverListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + [weakSelf.connection listen:query + tagId:tagId + hash:hash + onComplete:^(NSString *status) { + NSArray *events = onComplete(status); + [weakSelf.eventRaiser raiseEvents:events]; + }]; + // No synchronous events for network-backed sync trees + return @[]; + }; + serverListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tag) { + [weakSelf.connection unlisten:query tagId:tag]; + }; + self.serverSyncTree = + [[FSyncTree alloc] initWithPersistenceManager:self.persistenceManager + listenProvider:serverListenProvider]; + + [self restoreWrites]; + + [self updateInfo:kDotInfoConnected withValue:@NO]; + + [self setupNotifications]; +} + +- (void)restoreWrites { + NSArray *writes = self.persistenceManager.userWrites; + + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + __block NSInteger lastWriteId = NSIntegerMin; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + NSInteger writeId = write.writeId; + fbt_void_nsstring_nsstring callback = + ^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:write.path + status:status + message:@"Persisted write"]; + [self ackWrite:writeId + rerunTransactionsAtPath:write.path + status:status]; + }; + if (lastWriteId >= writeId) { + [NSException raise:NSInternalInconsistencyException + format:@"Restored writes were not in order!"]; + } + lastWriteId = writeId; + self.writeIdCounter = writeId + 1; + + if ([write isOverwrite]) { + FFLog(@"I-RDB038001", @"Restoring overwrite with id %ld", + (long)write.writeId); + [self.connection putData:[write.overwrite valForExport:YES] + forPath:[write.path toString] + withHash:nil + withCallback:callback]; + id resolved = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withSyncTree:self.serverSyncTree + atPath:write.path + serverValues:serverValues]; + [self.serverSyncTree applyUserOverwriteAtPath:write.path + newData:resolved + writeId:writeId + isVisible:YES]; + } else { + FFLog(@"I-RDB038002", @"Restoring merge with id %ld", + (long)write.writeId); + [self.connection mergeData:[write.merge valForExport:YES] + forPath:[write.path toString] + withCallback:callback]; + FCompoundWrite *resolved = [FServerValues + resolveDeferredValueCompoundWrite:write.merge + withSyncTree:self.serverSyncTree + atPath:write.path + serverValues:serverValues]; + [self.serverSyncTree applyUserMergeAtPath:write.path + changedChildren:resolved + writeId:writeId]; + } + }]; +} + +- (NSString *)name { + return self.repoInfo.namespace; +} + +- (NSString *)description { + return [self.repoInfo description]; +} + +- (void)interrupt { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; +} + +- (void)resume { + [self.connection resumeForReason:kFInterruptReasonRepoInterrupt]; +} + +// NOTE: Typically if you're calling this, you should be in an @autoreleasepool +// block to make sure that ARC kicks in and cleans up things no longer +// referenced (i.e. pendingPutsDB). +- (void)dispose { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; + + // We need to nil out any references to LevelDB, to make sure the + // LevelDB exclusive locks are released. + [self.persistenceManager close]; +} + +- (NSInteger)nextWriteId { + return self->_writeIdCounter++; +} + +- (NSTimeInterval)serverTime { + return [self.serverClock currentTime]; +} + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete { + id value = [node valForExport:YES]; + FFLog(@"I-RDB038003", @"Setting: %@ with %@ pri: %@", [path toString], + [value description], [[node getPriority] val]); + + // TODO: Optimize this behavior to either (a) store flag to skip resolving + // where possible and / or (b) store unresolved paths on JSON parse + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id existing = [self.serverSyncTree calcCompleteEventCacheAtPath:path + excludeWriteIds:@[]]; + id newNode = + [FServerValues resolveDeferredValueSnapshot:node + withExisting:existing + serverValues:serverValues]; + + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserOverwrite:node + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserOverwriteAtPath:path + newData:newNode + writeId:writeId + isVisible:YES]; + [self.eventRaiser raiseEvents:events]; + + [self.connection putData:value + forPath:[path toString] + withHash:nil + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"setValue: or removeValue:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:onComplete + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + FPath *affectedPath = [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; +} + +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + NSDictionary *values = [nodes valForExport:YES]; + + FFLog(@"I-RDB038004", @"Updating: %@ with %@", [path toString], + [values description]); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + FCompoundWrite *resolved = + [FServerValues resolveDeferredValueCompoundWrite:nodes + withSyncTree:self.serverSyncTree + atPath:path + serverValues:serverValues]; + + if (!resolved.isEmpty) { + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserMerge:nodes + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserMergeAtPath:path + changedChildren:resolved + writeId:writeId]; + [self.eventRaiser raiseEvents:events]; + + [self.connection mergeData:values + forPath:[path description] + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"updateChildValues:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + [nodes enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + FPath *pathFromRoot = [path child:childPath]; + FFLog(@"I-RDB038005", @"Cancelling transactions at path: %@", + pathFromRoot); + FPath *affectedPath = [self abortTransactionsAtPath:pathFromRoot + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + } else { + FFLog(@"I-RDB038006", @"update called with empty data. Doing nothing"); + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectCancelPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect forgetPath:path]; + } else { + FFLog(@"I-RDB038007", + @"cancelDisconnectOperations: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectPutData:[node valForExport:YES] + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect rememberData:node onPath:path]; + } else { + FFWarn(@"I-RDB038008", + @"onDisconnectSetValue: or " + @"onDisconnectRemoveValue: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + if (!nodes.isEmpty) { + NSDictionary *values = [nodes valForExport:YES]; + + [self.connection + onDisconnectMergeData:values + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = [status + isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [nodes enumerateWrites:^(FPath *relativePath, + id nodeUnresolved, + BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self.onDisconnect rememberData:nodeUnresolved + onPath:childPath]; + }]; + } else { + FFWarn(@"I-RDB038009", + @"onDisconnectUpdateChildValues: at %@ " + @"failed %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + } else { + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)purgeOutstandingWrites { + FFLog(@"I-RDB038010", @"Purging outstanding writes"); + NSArray *events = [self.serverSyncTree removeAllWrites]; + [self.eventRaiser raiseEvents:events]; + // Abort any transactions + [self abortTransactionsAtPath:[FPath empty] error:kFErrorWriteCanceled]; + // Remove outstanding writes from connection + [self.connection purgeOutstandingWrites]; +} + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } else { + events = [self.serverSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + // These are guaranteed not to raise events, since we're not passing in a + // cancelError. However we can future-proof a little bit by handling the + // return values anyways. + FFLog(@"I-RDB038011", @"Removing event registration with hande: %lu", + (unsigned long)eventRegistration.handle); + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } else { + events = [self.serverSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced { + NSAssert(![[query.path getFront] isEqualToString:kDotInfoPrefix], + @"Can't keep .info tree synced!"); + [self.serverSyncTree keepQuery:query synced:synced]; +} + +- (void)updateInfo:(NSString *)pathString withValue:(id)value { + // hack to make serverTimeOffset available in a threadsafe way. Property is + // marked as atomic + if ([pathString isEqualToString:kDotInfoServerTimeOffset]) { + NSTimeInterval offset = [(NSNumber *)value doubleValue] / 1000.0; + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] + offset:offset]; + } + + FPath *path = [[FPath alloc] + initWith:[NSString + stringWithFormat:@"%@/%@", kDotInfoPrefix, pathString]]; + id newNode = [FSnapshotUtilities nodeFrom:value]; + [self.infoData updateSnapshot:path withNewSnapshot:newNode]; + NSArray *events = [self.infoSyncTree applyServerOverwriteAtPath:path + newData:newNode]; + [self.eventRaiser raiseEvents:events]; +} + +- (void)callOnComplete:(fbt_void_nserror_ref)onComplete + withStatus:(NSString *)status + errorReason:(NSString *)errorReason + andPath:(FPath *)path { + if (onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + BOOL statusOk = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSError *err = nil; + if (!statusOk) { + err = [FUtilities errorForStatus:status andReason:errorReason]; + } + [self.eventRaiser raiseCallback:^{ + onComplete(err, ref); + }]; + } +} + +- (void)ackWrite:(NSInteger)writeId + rerunTransactionsAtPath:(FPath *)path + status:(NSString *)status { + if ([status isEqualToString:kFErrorWriteCanceled]) { + // This write was already removed, we just need to ignore it... + } else { + BOOL success = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSArray *clearEvents = + [self.serverSyncTree ackUserWriteWithWriteId:writeId + revert:!success + persist:YES + clock:self.serverClock]; + if ([clearEvents count] > 0) { + [self rerunTransactionsForPath:path]; + } + [self.eventRaiser raiseEvents:clearEvents]; + } +} + +- (void)warnIfWriteFailedAtPath:(FPath *)path + status:(NSString *)status + message:(NSString *)message { + if (!([status isEqualToString:kFWPResponseForActionStatusOk] || + [status isEqualToString:kFErrorWriteCanceled])) { + FFWarn(@"I-RDB038012", @"%@ at %@ failed: %@", message, path, status); + } +} + +#pragma mark - +#pragma mark FPersistentConnectionDelegate methods + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)data + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB038013", @"onDataUpdateForPath: %@ withMessage: %@", + pathString, data); + + // For testing. + self.dataUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + data = self.interceptServerDataCallback + ? self.interceptServerDataCallback(pathString, data) + : data; + NSArray *events = nil; + + if (tagId != nil) { + if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *taggedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = + [self.serverSyncTree applyTaggedQueryMergeAtPath:path + changedChildren:taggedChildren + tagId:tagId]; + } else { + id taggedSnap = [FSnapshotUtilities nodeFrom:data]; + events = + [self.serverSyncTree applyTaggedQueryOverwriteAtPath:path + newData:taggedSnap + tagId:tagId]; + } + } else if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *changedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = [self.serverSyncTree applyServerMergeAtPath:path + changedChildren:changedChildren]; + } else { + id snap = [FSnapshotUtilities nodeFrom:data]; + events = [self.serverSyncTree applyServerOverwriteAtPath:path + newData:snap]; + } + + if ([events count] > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)pathString + tagId:(NSNumber *)tag { + FFLog(@"I-RDB038014", @"onRangeMerge: %@ => %@", pathString, ranges); + + // For testing + self.rangeMergeUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + NSArray *events; + if (tag != nil) { + events = [self.serverSyncTree applyTaggedServerRangeMergeAtPath:path + updates:ranges + tagId:tag]; + } else { + events = [self.serverSyncTree applyServerRangeMergeAtPath:path + updates:ranges]; + } + if (events.count > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onConnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@YES]; +} + +- (void)onDisconnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@NO]; + [self runOnDisconnectEvents]; +} + +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates { + for (NSString *key in updates) { + id val = [updates objectForKey:key]; + [self updateInfo:key withValue:val]; + } +} + +- (void)setupNotifications { + NSString *const *backgroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationDidEnterBackgroundNotification"); + if (backgroundConstant) { + FFLog(@"I-RDB038015", @"Registering for background notification."); + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didEnterBackground) + name:*backgroundConstant + object:nil]; + } else { + FFLog(@"I-RDB038016", + @"Skipped registering for background notification."); + } +} + +- (void)didEnterBackground { + if (!self.config.persistenceEnabled) + return; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + // The idea is to wait until any outstanding sets get written to disk. Since + // the sets might still be in our dispatch queue, we wait for the dispatch + // queue to catch up and for persistence to catch up. This may be + // undesirable though. The dispatch queue might just be processing a bunch + // of incoming data or something. We might want to keep track of whether + // there are any unpersisted sets or something. + FFLog(@"I-RDB038017", + @"Entering background. Starting background task to finish work."); + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + assert(uiApplicationClass); // If we are here, we should be on iOS and + // UIApplication should be available. + + UIApplication *application = [uiApplicationClass sharedApplication]; + __block UIBackgroundTaskIdentifier bgTask = + [application beginBackgroundTaskWithExpirationHandler:^{ + [application endBackgroundTask:bgTask]; + }]; + + NSDate *start = [NSDate date]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + NSTimeInterval finishTime = [start timeIntervalSinceNow] * -1; + FFLog(@"I-RDB038018", @"Background task completed. Queue time: %f", + finishTime); + [application endBackgroundTask:bgTask]; + }); +#endif +} + +#pragma mark - +#pragma mark Internal methods + +/** + * Applies all the changes stored up in the onDisconnect tree + */ +- (void)runOnDisconnectEvents { + FFLog(@"I-RDB038019", @"Running onDisconnectEvents"); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + NSMutableArray *events = [[NSMutableArray alloc] init]; + + [self.onDisconnect + forEachTreeAtPath:[FPath empty] + do:^(FPath *path, id node) { + id existing = [self.serverSyncTree + calcCompleteEventCacheAtPath:path + excludeWriteIds:@[]]; + id resolved = [FServerValues + resolveDeferredValueSnapshot:node + withExisting:existing + serverValues:serverValues]; + [events addObjectsFromArray: + [self.serverSyncTree + applyServerOverwriteAtPath:path + newData:resolved]]; + FPath *affectedPath = + [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + [self.eventRaiser raiseEvents:events]; +} + +- (NSDictionary *)dumpListens { + return [self.connection dumpListens]; +} + +#pragma mark - +#pragma mark Transactions + +/** + * Setup the transaction data structures + */ +- (void)initTransactions { + self.transactionQueueTree = [[FTree alloc] init]; + self.hijackHash = NO; + self.loggedTransactionPersistenceWarning = NO; +} + +/** + * Creates a new transaction, add its to the transactions we're tracking, and + * sends it to the server if possible + */ +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally { + if (self.config.persistenceEnabled && + !self.loggedTransactionPersistenceWarning) { + self.loggedTransactionPersistenceWarning = YES; + FFInfo(@"I-RDB038020", + @"runTransactionBlock: usage detected while persistence is " + @"enabled. Please be aware that transactions " + @"*will not* be persisted across app restarts. " + @"See " + @"https://www.firebase.com/docs/ios/guide/" + @"offline-capabilities.html#section-handling-transactions-" + @"offline for more details."); + } + + FIRDatabaseReference *watchRef = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + // make sure we're listening on this node + // Note: we can't do this asynchronously. To preserve event ordering, it has + // to be done in this block. This is ok, this block is guaranteed to be our + // own event loop + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + fbt_void_datasnapshot cb = ^(FIRDataSnapshot *snapshot) { + }; + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self + handle:handle + callback:cb + cancelCallback:nil]; + [watchRef.repo addEventRegistration:registration + forQuery:watchRef.querySpec]; + fbt_void_void unwatcher = ^{ + [watchRef removeObserverWithHandle:handle]; + }; + + // Save all the data that represents this transaction + FTupleTransaction *transaction = [[FTupleTransaction alloc] init]; + transaction.path = path; + transaction.update = update; + transaction.onComplete = onComplete; + transaction.status = FTransactionInitializing; + transaction.order = [FUtilities LUIDGenerator]; + transaction.applyLocally = applyLocally; + transaction.retryCount = 0; + transaction.unwatcher = unwatcher; + transaction.currentWriteId = nil; + transaction.currentInputSnapshot = nil; + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + + // Run transaction initially + id currentState = [self latestStateAtPath:path excludeWriteIds:nil]; + transaction.currentInputSnapshot = currentState; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentState]; + FIRTransactionResult *result = transaction.update(mutableCurrent); + + if (!result.isSuccess) { + // Abort the transaction + transaction.unwatcher(); + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + if (transaction.onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self + path:transaction.path]; + FIndexedNode *indexedNode = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + [self.eventRaiser raiseCallback:^{ + transaction.onComplete(nil, NO, snap); + }]; + } + } else { + // Note: different from js. We don't need to validate, FIRMutableData + // does validation. We also don't have to worry about priorities. Just + // mark as run and add to queue. + transaction.status = FTransactionRun; + FTree *queueNode = [self.transactionQueueTree subTree:transaction.path]; + NSMutableArray *nodeQueue = [queueNode getValue]; + if (nodeQueue == nil) { + nodeQueue = [[NSMutableArray alloc] init]; + } + [nodeQueue addObject:transaction]; + [queueNode setValue:nodeQueue]; + + // Update visibleData and raise events + // Note: We intentionally raise events after updating all of our + // transaction state, since the user could start new transactions from + // the event callbacks + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id newValUnresolved = [result.update nodeValue]; + id newVal = + [FServerValues resolveDeferredValueSnapshot:newValUnresolved + withExisting:currentState + serverValues:serverValues]; + transaction.currentOutputSnapshotRaw = newValUnresolved; + transaction.currentOutputSnapshotResolved = newVal; + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + + NSArray *events = [self.serverSyncTree + applyUserOverwriteAtPath:path + newData:newVal + writeId:[transaction.currentWriteId integerValue] + isVisible:transaction.applyLocally]; + [self.eventRaiser raiseEvents:events]; + + [self sendAllReadyTransactions]; + } +} + +/** + * @param writeIdsToExclude A specific set to exclude + */ +- (id)latestStateAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + id latestState = + [self.serverSyncTree calcCompleteEventCacheAtPath:path + excludeWriteIds:writeIdsToExclude]; + return latestState ? latestState : [FEmptyNode emptyNode]; +} + +/** + * Sends any already-run transactions that aren't waiting for outstanding + * transactions to complete. + * + * Externally, call the version with no arguments. + * Internally, calls itself recursively with a particular transactionQueueTree + * node to recurse through the tree + */ +- (void)sendAllReadyTransactions { + FTree *node = self.transactionQueueTree; + + [self pruneCompletedTransactionsBelowNode:node]; + [self sendReadyTransactionsForTree:node]; +} + +- (void)sendReadyTransactionsForTree:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + queue = [self buildTransactionQueueAtNode:node]; + NSAssert([queue count] > 0, @"Sending zero length transaction queue"); + + NSUInteger notRunIndex = [queue + indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { + return ((FTupleTransaction *)obj).status != FTransactionRun; + }]; + + // If they're all run (and not sent), we can send them. Else, we must + // wait. + if (notRunIndex == NSNotFound) { + [self sendTransactionQueue:queue atPath:node.path]; + } + } else if ([node hasChildren]) { + [node forEachChild:^(FTree *child) { + [self sendReadyTransactionsForTree:child]; + }]; + } +} + +/** + * Given a list of run transactions, send them to the server and then handle the + * result (success or failure). + */ +- (void)sendTransactionQueue:(NSMutableArray *)queue atPath:(FPath *)path { + // Mark transactions as sent and bump the retry count + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + id latestState = [self latestStateAtPath:path + excludeWriteIds:writeIdsToExclude]; + id snapToSend = latestState; + NSString *latestHash = [latestState dataHash]; + for (FTupleTransaction *transaction in queue) { + NSAssert( + transaction.status == FTransactionRun, + @"[FRepo sendTransactionQueue:] items in queue should all be run."); + FFLog(@"I-RDB038021", @"Transaction at %@ set to SENT", + transaction.path); + transaction.status = FTransactionSent; + transaction.retryCount++; + FPath *relativePath = [FPath relativePathFrom:path to:transaction.path]; + // If we've gotten to this point, the output snapshot must be defined. + snapToSend = + [snapToSend updateChild:relativePath + withNewChild:transaction.currentOutputSnapshotRaw]; + } + + id dataToSend = [snapToSend valForExport:YES]; + NSString *pathToSend = [path description]; + latestHash = self.hijackHash ? @"badhash" : latestHash; + + // Send the put + [self.connection + putData:dataToSend + forPath:pathToSend + withHash:latestHash + withCallback:^(NSString *status, NSString *errorReason) { + FFLog(@"I-RDB038022", @"Transaction put response: %@ : %@", + pathToSend, status); + + NSMutableArray *events = [[NSMutableArray alloc] init]; + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + // Queue up the callbacks and fire them after cleaning up all of + // our transaction state, since the callback could trigger more + // transactions or sets. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionCompleted; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:NO + persist:NO + clock:self.serverClock]]; + if (transaction.onComplete) { + // We never unset the output snapshot, and given that this + // transaction is complete, it should be set + id node = + transaction.currentOutputSnapshotResolved; + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:node]; + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + fbt_void_void cb = ^{ + transaction.onComplete(nil, YES, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + transaction.unwatcher(); + } + + // Now remove the completed transactions. + [self + pruneCompletedTransactionsBelowNode:[self.transactionQueueTree + subTree:path]]; + // There may be pending transactions that we can now send. + [self sendAllReadyTransactions]; + + // Finally, trigger onComplete callbacks + [self.eventRaiser raiseCallbacks:callbacks]; + } else { + // transactions are no longer sent. Update their status + // appropriately. + if ([status + isEqualToString:kFWPResponseForActionStatusDataStale]) { + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + transaction.status = FTransactionNeedsAbort; + } else { + transaction.status = FTransactionRun; + } + } + } else { + FFWarn(@"I-RDB038023", + @"runTransactionBlock: at %@ failed: %@", path, + status); + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionNeedsAbort; + [transaction setAbortStatus:status reason:errorReason]; + } + } + } + + [self rerunTransactionsForPath:path]; + [self.eventRaiser raiseEvents:events]; + }]; +} + +/** + * Finds all transactions dependent on the data at changed Path and reruns them. + * + * Should be called any time cached data changes. + * + * Return the highest path that was affected by rerunning transactions. This is + * the path at which events need to be raised for. + */ +- (FPath *)rerunTransactionsForPath:(FPath *)changedPath { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return changedPath; + } else { + FTree *rootMostTransactionNode = + [self getAncestorTransactionNodeForPath:changedPath]; + FPath *path = rootMostTransactionNode.path; + + NSArray *queue = + [self buildTransactionQueueAtNode:rootMostTransactionNode]; + [self rerunTransactionQueue:queue atPath:path]; + + return path; + } +} + +/** + * Does all the work of rerunning transactions (as well as cleans up aborted + * transactions and whatnot). + */ +- (void)rerunTransactionQueue:(NSArray *)queue atPath:(FPath *)path { + if (queue.count == 0) { + return; // nothing to do + } + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since the callback could trigger more transactions or + // sets. + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Ignore, by default, all of the sets in this queue, since we're re-running + // all of them. However, we want to include the results of new sets + // triggered as part of this re-run, so we don't want to ignore a range, + // just these specific sets. + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + + for (FTupleTransaction *transaction in queue) { + FPath *relativePath __unused = + [FPath relativePathFrom:path to:transaction.path]; + BOOL abortTransaction = NO; + NSAssert(relativePath != nil, @"[FRepo rerunTransactionsQueue:] " + @"relativePath should not be null."); + + if (transaction.status == FTransactionNeedsAbort) { + abortTransaction = YES; + if (![transaction.abortStatus + isEqualToString:kFErrorWriteCanceled]) { + NSArray *ackEvents = [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]; + [events addObjectsFromArray:ackEvents]; + } + } else if (transaction.status == FTransactionRun) { + if (transaction.retryCount >= kFTransactionMaxRetries) { + abortTransaction = YES; + [transaction setAbortStatus:kFTransactionTooManyRetries + reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // This code reruns a transaction + id currentNode = + [self latestStateAtPath:transaction.path + excludeWriteIds:writeIdsToExclude]; + transaction.currentInputSnapshot = currentNode; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentNode]; + FIRTransactionResult *result = + transaction.update(mutableCurrent); + if (result.isSuccess) { + NSNumber *oldWriteId = transaction.currentWriteId; + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + + id newVal = [result.update nodeValue]; + id newValResolved = [FServerValues + resolveDeferredValueSnapshot:newVal + withExisting:transaction + .currentInputSnapshot + serverValues:serverValues]; + + transaction.currentOutputSnapshotRaw = newVal; + transaction.currentOutputSnapshotResolved = newValResolved; + + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + // Mutates writeIdsToExclude in place + [writeIdsToExclude removeObject:oldWriteId]; + [events + addObjectsFromArray: + [self.serverSyncTree + applyUserOverwriteAtPath:transaction.path + newData: + transaction + .currentOutputSnapshotResolved + writeId: + [transaction.currentWriteId + integerValue] + isVisible:transaction + .applyLocally]]; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[oldWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + abortTransaction = YES; + // The user aborted the transaction. JS treats ths as a + // "nodata" abort, but it's not an error, so we don't send + // them an error. + [transaction setAbortStatus:nil reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } + } + } + + [self.eventRaiser raiseEvents:events]; + events = nil; + + if (abortTransaction) { + // Abort + transaction.status = FTransactionCompleted; + transaction.unwatcher(); + if (transaction.onComplete) { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIndexedNode *lastInput = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:lastInput]; + fbt_void_void cb = ^{ + // Unlike JS, no need to check for "nodata" because ObjC has + // abortError = nil + transaction.onComplete(transaction.abortError, NO, snap); + }; + [callbacks addObject:[cb copy]]; + } + } + } + + // Note: unlike current js client, we don't need to preserve priority. Users + // can set priority via FIRMutableData + + // Clean up completed transactions. + [self pruneCompletedTransactionsBelowNode:self.transactionQueueTree]; + + // Now fire callbacks, now that we're in a good, known state. + [self.eventRaiser raiseCallbacks:callbacks]; + + // Try to send the transaction result to the server + [self sendAllReadyTransactions]; +} + +- (FTree *)getAncestorTransactionNodeForPath:(FPath *)path { + FTree *transactionNode = self.transactionQueueTree; + + while (![path isEmpty] && [transactionNode getValue] == nil) { + NSString *front = [path getFront]; + transactionNode = + [transactionNode subTree:[[FPath alloc] initWith:front]]; + path = [path popFront]; + } + + return transactionNode; +} + +- (NSMutableArray *)buildTransactionQueueAtNode:(FTree *)node { + NSMutableArray *queue = [[NSMutableArray alloc] init]; + [self aggregateTransactionQueuesForNode:node andQueue:queue]; + + [queue sortUsingComparator:^NSComparisonResult(FTupleTransaction *obj1, + FTupleTransaction *obj2) { + return [obj1.order compare:obj2.order]; + }]; + + return queue; +} + +- (void)aggregateTransactionQueuesForNode:(FTree *)node + andQueue:(NSMutableArray *)queue { + NSArray *nodeQueue = [node getValue]; + [queue addObjectsFromArray:nodeQueue]; + + [node forEachChild:^(FTree *child) { + [self aggregateTransactionQueuesForNode:child andQueue:queue]; + }]; +} + +/** + * Remove COMPLETED transactions at or below this node in the + * transactionQueueTree + */ +- (void)pruneCompletedTransactionsBelowNode:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + int i = 0; + // remove all of the completed transactions from the queue + while (i < queue.count) { + FTupleTransaction *transaction = [queue objectAtIndex:i]; + if (transaction.status == FTransactionCompleted) { + [queue removeObjectAtIndex:i]; + } else { + i++; + } + } + if (queue.count > 0) { + [node setValue:queue]; + } else { + [node setValue:nil]; + } + } + + [node forEachChildMutationSafe:^(FTree *child) { + [self pruneCompletedTransactionsBelowNode:child]; + }]; +} + +/** + * Aborts all transactions on ancestors or descendants of the specified path. + * Called when doing a setValue: or updateChildValues: since we consider them + * incompatible with transactions + * + * @param path path for which we want to abort related transactions. + */ +- (FPath *)abortTransactionsAtPath:(FPath *)path error:(NSString *)error { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return path; + } else { + FPath *affectedPath = + [self getAncestorTransactionNodeForPath:path].path; + + FTree *transactionNode = [self.transactionQueueTree subTree:path]; + [transactionNode forEachAncestor:^BOOL(FTree *ancestor) { + [self abortTransactionsAtNode:ancestor error:error]; + return NO; + }]; + + [self abortTransactionsAtNode:transactionNode error:error]; + + [transactionNode forEachDescendant:^(FTree *child) { + [self abortTransactionsAtNode:child error:error]; + }]; + + return affectedPath; + } +} + +/** + * Abort transactions stored in this transactions queue node. + * + * @param node Node to abort transactions for. + */ +- (void)abortTransactionsAtNode:(FTree *)node error:(NSString *)error { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since can be immediately aborted and removed. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Go through queue. Any already-sent transactions must be marked for + // abort, while the unsent ones can be immediately aborted and removed + NSMutableArray *events = [[NSMutableArray alloc] init]; + int lastSent = -1; + // Note: all of the sent transactions will be at the front of the queue, + // so safe to increment lastSent + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + // No-op. already marked. + } else if (transaction.status == FTransactionSent) { + // Mark this transaction for abort when it returns + lastSent++; + transaction.status = FTransactionSentNeedsAbort; + [transaction setAbortStatus:error reason:nil]; + } else { + // we can abort this immediately + transaction.unwatcher(); + if ([error isEqualToString:kFTransactionSet]) { + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // If it was cancelled it was already removed from the sync + // tree, no need to ack + NSAssert([error isEqualToString:kFErrorWriteCanceled], nil); + } + + if (transaction.onComplete) { + NSError *abortReason = [FUtilities errorForStatus:error + andReason:nil]; + FIRDataSnapshot *snapshot = nil; + fbt_void_void cb = ^{ + transaction.onComplete(abortReason, NO, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + } + } + if (lastSent == -1) { + // We're not waiting for any sent transactions. We can clear the + // queue. + [node setValue:nil]; + } else { + // Remove the transactions we aborted + NSRange theRange; + theRange.location = lastSent + 1; + theRange.length = queue.count - theRange.location; + [queue removeObjectsInRange:theRange]; + } + + // Now fire the callbacks + [self.eventRaiser raiseEvents:events]; + [self.eventRaiser raiseCallbacks:callbacks]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h new file mode 100644 index 00000000..46e9b8b7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FRepoInfo : NSObject + +@property(nonatomic, readonly, strong) NSString *host; +@property(nonatomic, readonly, strong) NSString *namespace; +@property(nonatomic, strong) NSString *internalHost; +@property(nonatomic, readonly) bool secure; + +- (id)initWithHost:(NSString *)host + isSecure:(bool)secure + withNamespace:(NSString *)namespace; + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID; +- (NSString *)connectionURL; +- (void)clearInternalHostCache; +- (BOOL)isDemoHost; +- (BOOL)isCustomHost; + +- (id)copyWithZone:(NSZone *)zone; +- (NSUInteger)hash; +- (BOOL)isEqual:(id)anObject; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m new file mode 100644 index 00000000..b2dd2e26 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoInfo.h" +#import "FConstants.h" + +@interface FRepoInfo () + +@property(nonatomic, strong) NSString *domain; + +@end + +@implementation FRepoInfo + +@synthesize namespace; +@synthesize host; +@synthesize internalHost; +@synthesize secure; +@synthesize domain; + +- (id)initWithHost:(NSString *)aHost + isSecure:(bool)isSecure + withNamespace:(NSString *)aNamespace { + self = [super init]; + if (self) { + host = aHost; + domain = + [host containsString:@"."] + ? [host + substringFromIndex:[host rangeOfString:@"."].location + 1] + : host; + secure = isSecure; + namespace = aNamespace; + + // Get cached internal host if it exists + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSString *cachedInternalHost = [[NSUserDefaults standardUserDefaults] + stringForKey:internalHostKey]; + if (cachedInternalHost != nil) { + internalHost = cachedInternalHost; + } else { + internalHost = self.host; + } + } + return self; +} + +- (NSString *)description { + // The namespace is encoded in the hostname, so we can just return this. + return [NSString + stringWithFormat:@"http%@://%@", (self.secure ? @"s" : @""), self.host]; +} + +- (void)setInternalHost:(NSString *)newHost { + if (![internalHost isEqualToString:newHost]) { + internalHost = newHost; + + // Cache the internal host so we don't need to redirect later on + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache setObject:internalHost forKey:internalHostKey]; + [cache synchronize]; + } +} + +- (void)clearInternalHostCache { + internalHost = self.host; + + // Remove the cached entry + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache removeObjectForKey:internalHostKey]; + [cache synchronize]; +} + +- (BOOL)isDemoHost { + return [self.domain isEqualToString:@"firebaseio-demo.com"]; +} + +- (BOOL)isCustomHost { + return ![self.domain isEqualToString:@"firebaseio-demo.com"] && + ![self.domain isEqualToString:@"firebaseio.com"]; +} + +- (NSString *)connectionURL { + return [self connectionURLWithLastSessionID:nil]; +} + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID { + NSString *scheme; + if (self.secure) { + scheme = @"wss"; + } else { + scheme = @"ws"; + } + NSString *url = + [NSString stringWithFormat:@"%@://%@/.ws?%@=%@&ns=%@", scheme, + self.internalHost, kWireProtocolVersionParam, + kWebsocketProtocolVersion, self.namespace]; + + if (lastSessionID != nil) { + url = [NSString stringWithFormat:@"%@&ls=%@", url, lastSessionID]; + } + return url; +} + +- (id)copyWithZone:(NSZone *)zone; +{ + return self; // Immutable +} + +- (NSUInteger)hash { + NSUInteger result = host.hash; + result = 31 * result + (secure ? 1 : 0); + result = 31 * result + namespace.hash; + result = 31 * result + host.hash; + return result; +} + +- (BOOL)isEqual:(id)anObject { + if (![anObject isKindOfClass:[FRepoInfo class]]) + return NO; + FRepoInfo *other = (FRepoInfo *)anObject; + return secure == other.secure && [host isEqualToString:other.host] && + [namespace isEqualToString:other.namespace]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h new file mode 100644 index 00000000..ba8d1fc7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FRepo.h" +#import "FRepoInfo.h" +#import + +@interface FRepoManager : NSObject + ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config; ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; ++ (void)interruptAll; ++ (void)interrupt:(FIRDatabaseConfig *)config; ++ (void)resumeAll; ++ (void)resume:(FIRDatabaseConfig *)config; ++ (void)disposeRepos:(FIRDatabaseConfig *)config; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m new file mode 100644 index 00000000..d018cdb2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m @@ -0,0 +1,148 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoManager.h" +#import "FAtomicNumber.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepo.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@implementation FRepoManager + +typedef NSMutableDictionary *> + FRepoDictionary; + ++ (FRepoDictionary *)configs { + static dispatch_once_t pred = 0; + static FRepoDictionary *configs; + dispatch_once(&pred, ^{ + configs = [NSMutableDictionary dictionary]; + }); + return configs; +} + +/** + * Used for legacy unit tests. The public API should go through + * FirebaseDatabase which calls createRepo. + */ ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos || repos[repoInfo] == nil) { + // Calling this should create the repo. + [FIRDatabase createDatabaseForTests:repoInfo config:config]; + } + + return configs[config.sessionIdentifier][repoInfo]; + } +} + ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos) { + repos = [NSMutableDictionary dictionary]; + configs[config.sessionIdentifier] = repos; + } + FRepo *repo = repos[repoInfo]; + if (repo == nil) { + repo = [[FRepo alloc] initWithRepoInfo:repoInfo + config:config + database:database]; + repos[repoInfo] = repo; + return repo; + } else { + [NSException + raise:@"RepoExists" + format:@"createRepo called for Repo that already exists."]; + return nil; + } + } +} + ++ (void)interrupt:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + }); +} + ++ (void)interruptAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + } + }); +} + ++ (void)resume:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + }); +} + ++ (void)resumeAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + } + }); +} + ++ (void)disposeRepos:(FIRDatabaseConfig *)config { + // Do this synchronously to make sure we release our references to LevelDB + // before returning, allowing LevelDB to close and release its exclusive + // locks. + dispatch_sync([FIRDatabaseQuery sharedQueue], ^{ + FFLog(@"I-RDB040001", @"Disposing all repos for Config with name %@", + config.sessionIdentifier); + NSMutableDictionary *configs = [FRepoManager configs]; + for (FRepo *repo in [configs[config.sessionIdentifier] allValues]) { + [repo dispose]; + } + [configs removeObjectForKey:config.sessionIdentifier]; + }); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h new file mode 100644 index 00000000..8dc13507 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepo.h" +#import "FSparseSnapshotTree.h" + +@class FSyncTree; +@class FAtomicNumber; +@class FEventRaiser; +@class FSnapshotHolder; + +@interface FRepo () + +- (void)runOnDisconnectEvents; + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPersistentConnection *connection; +@property(nonatomic, strong) FSnapshotHolder *infoData; +@property(nonatomic, strong) FSparseSnapshotTree *onDisconnect; +@property(nonatomic, strong) FEventRaiser *eventRaiser; +@property(nonatomic, strong) FSyncTree *serverSyncTree; + +// For testing. +@property(nonatomic) long dataUpdateCount; +@property(nonatomic) long rangeMergeUpdateCount; + +- (NSInteger)nextWriteId; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h new file mode 100644 index 00000000..c4dc7c54 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FSparseSnapshotTree.h" +#import "FSyncTree.h" +#import + +@interface FServerValues : NSObject + ++ (NSDictionary *)generateServerValues:(id)clock; + ++ (FCompoundWrite *)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withSyncTree:(FSyncTree *)tree + atPath:(FPath *)path + serverValues: + (NSDictionary *)serverValues; ++ (id)resolveDeferredValueSnapshot:(id)node + withSyncTree:(FSyncTree *)existing + atPath:(FPath *)path + serverValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueSnapshot:(id)node + withExisting:(id)existing + serverValues:(NSDictionary *)serverValues; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m new file mode 100644 index 00000000..dfda2d65 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m @@ -0,0 +1,269 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FServerValues.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" + +const NSString *kTimestamp = @"timestamp"; +const NSString *kIncrement = @"increment"; + +BOOL canBeRepresentedAsLong(NSNumber *num) { + switch (num.objCType[0]) { + case 'f': // float; fallthrough + case 'd': // double + return NO; + case 'L': // unsigned long; fallthrough + case 'Q': // unsigned long long; fallthrough + // Only use ulong(long) if there isn't an overflow. + if (num.unsignedLongLongValue > LONG_MAX) { + return NO; + } + } + return YES; +} + +// Running through CompoundWrites for all update paths has been shown to +// be a 20% pessimization in microbenchmarks. This is because it slows +// down by O(N) of the write queue length. To eliminate the performance +// hit, we wrap around existing data of either snapshot or CompoundWrite +// (allowing us to share code) and read from the CompoundWrite only when/where +// we need to calculate an incremented value's prior state. +@protocol ValueProvider +- (id)getChild:(NSString *)pathSegment; +- (id)value; +@end + +@interface DeferredValueProvider : NSObject +- (instancetype)initWithSyncTree:(FSyncTree *)tree atPath:(FPath *)path; +- (id)getChild:(NSString *)pathSegment; +- (id)value; +@property FPath *path; +@property FSyncTree *tree; +@end + +@interface ExistingValueProvider : NSObject +- (instancetype)initWithSnapshot:(id)snapshot; +- (id)getChild:(NSString *)pathSegment; +- (id)value; +@property id snapshot; +@end + +@implementation DeferredValueProvider +- (instancetype)initWithSyncTree:(FSyncTree *)tree atPath:(FPath *)path { + self.tree = tree; + self.path = path; + return self; +} + +- (id)getChild:(NSString *)pathSegment { + FPath *child = [self.path childFromString:pathSegment]; + return [[DeferredValueProvider alloc] initWithSyncTree:self.tree + atPath:child]; +} + +- (id)value { + return [self.tree calcCompleteEventCacheAtPath:self.path + excludeWriteIds:@[]]; +} +@end + +@implementation ExistingValueProvider +- (instancetype)initWithSnapshot:(id)snapshot { + self.snapshot = snapshot; + return self; +} + +- (id)getChild:(NSString *)pathSegment { + return [[ExistingValueProvider alloc] + initWithSnapshot:[self.snapshot getImmediateChild:pathSegment]]; +} + +- (id)value { + return self.snapshot; +} +@end + +@interface FServerValues () ++ (id)resolveScalarServerOp:(NSString *)op + withServerValues:(NSDictionary *)serverValues; ++ (id)resolveComplexServerOp:(NSDictionary *)op + withValueProvider:(id)existing + serverValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueSnapshot:(id)node + withValueProvider:(id)existing + serverValues:(NSDictionary *)serverValues; + +@end + +@implementation FServerValues + ++ (NSDictionary *)generateServerValues:(id)clock { + long long millis = (long long)([clock currentTime] * 1000); + return @{kTimestamp : [NSNumber numberWithLongLong:millis]}; +} + ++ (id)resolveDeferredValue:(id)val + withExisting:(id)existing + serverValues:(NSDictionary *)serverValues { + if (![val isKindOfClass:[NSDictionary class]]) { + return val; + } + NSDictionary *dict = val; + id op = dict[kServerValueSubKey]; + + if (op == nil) { + return val; + } else if ([op isKindOfClass:NSString.class]) { + return [FServerValues resolveScalarServerOp:op + withServerValues:serverValues]; + } else if ([op isKindOfClass:NSDictionary.class]) { + return [FServerValues resolveComplexServerOp:op + withValueProvider:existing + serverValues:serverValues]; + } + return val; +} + ++ (id)resolveScalarServerOp:(NSString *)op + withServerValues:(NSDictionary *)serverValues { + return serverValues[op]; +} + ++ (id)resolveComplexServerOp:(NSDictionary *)op + withValueProvider:(id)jitExisting + serverValues:(NSDictionary *)serverValues { + // Only increment is supported as of now + if (op[kIncrement] == nil) { + return nil; + } + + // Incrementing a non-number sets the value to the incremented amount + NSNumber *delta = op[kIncrement]; + id existing = jitExisting.value; + if (![existing isLeafNode]) { + return delta; + } + FLeafNode *existingLeaf = existing; + if (![existingLeaf.value isKindOfClass:NSNumber.class]) { + return delta; + } + + NSNumber *existingNum = existingLeaf.value; + BOOL incrLong = canBeRepresentedAsLong(delta); + BOOL baseLong = canBeRepresentedAsLong(existingNum); + + if (incrLong && baseLong) { + long x = delta.longValue; + long y = existingNum.longValue; + long r = x + y; + + // See "Hacker's Delight" 2-12: Overflow if both arguments have the + // opposite sign of the result + if (((x ^ r) & (y ^ r)) >= 0) { + return @(r); + } + } + return @(delta.doubleValue + existingNum.doubleValue); +} + ++ (FCompoundWrite *)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withSyncTree:(FSyncTree *)tree + atPath:(FPath *)path + serverValues: + (NSDictionary *)serverValues { + __block FCompoundWrite *resolved = write; + [write enumerateWrites:^(FPath *subPath, id node, BOOL *stop) { + id existing = + [[DeferredValueProvider alloc] initWithSyncTree:tree + atPath:[path child:subPath]]; + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:node + withValueProvider:existing + serverValues:serverValues]; + // Node actually changed, use pointer inequality here + if (resolvedNode != node) { + resolved = [resolved addWrite:resolvedNode atPath:subPath]; + } + }]; + return resolved; +} + ++ (id)resolveDeferredValueSnapshot:(id)node + withSyncTree:(FSyncTree *)tree + atPath:(FPath *)path + serverValues:(NSDictionary *)serverValues { + id jitExisting = + [[DeferredValueProvider alloc] initWithSyncTree:tree atPath:path]; + return [FServerValues resolveDeferredValueSnapshot:node + withValueProvider:jitExisting + serverValues:serverValues]; +} + ++ (id)resolveDeferredValueSnapshot:(id)node + withExisting:(id)existing + serverValues:(NSDictionary *)serverValues { + id jitExisting = + [[ExistingValueProvider alloc] initWithSnapshot:existing]; + return [FServerValues resolveDeferredValueSnapshot:node + withValueProvider:jitExisting + serverValues:serverValues]; +} + ++ (id)resolveDeferredValueSnapshot:(id)node + withValueProvider:(id)existing + serverValues:(NSDictionary *)serverValues { + id priorityVal = + [FServerValues resolveDeferredValue:[[node getPriority] val] + withExisting:[existing getChild:@".priority"] + serverValues:serverValues]; + id priority = [FSnapshotUtilities nodeFrom:priorityVal]; + + if ([node isLeafNode]) { + id value = [self resolveDeferredValue:[node val] + withExisting:existing + serverValues:serverValues]; + if (![value isEqual:[node val]] || + ![priority isEqual:[node getPriority]]) { + return [[FLeafNode alloc] initWithValue:value + withPriority:priority]; + } else { + return node; + } + } else { + __block FChildrenNode *newNode = node; + if (![priority isEqual:[node getPriority]]) { + newNode = [newNode updatePriority:priority]; + } + + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + id newChildNode = [FServerValues + resolveDeferredValueSnapshot:childNode + withValueProvider:[existing getChild:childKey] + serverValues:serverValues]; + if (![newChildNode isEqual:childNode]) { + newNode = [newNode updateImmediateChild:childKey + withNewChild:newChildNode]; + } + }]; + return newNode; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h new file mode 100644 index 00000000..d682a8e2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FSnapshotHolder : NSObject + +- (id)getNode:(FPath *)path; +- (void)updateSnapshot:(FPath *)path withNewSnapshot:(id)newSnapshotNode; + +@property(nonatomic, strong) id rootNode; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m new file mode 100644 index 00000000..59a7b521 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotHolder.h" +#import "FEmptyNode.h" + +@interface FSnapshotHolder () + +@end + +@implementation FSnapshotHolder + +@synthesize rootNode; + +- (id)init { + self = [super init]; + if (self) { + self.rootNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)getNode:(FPath *)path { + return [self.rootNode getChild:path]; +} + +- (void)updateSnapshot:(FPath *)path + withNewSnapshot:(id)newSnapshotNode { + self.rootNode = [self.rootNode updateChild:path + withNewChild:newSnapshotNode]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h new file mode 100644 index 00000000..dab5406c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@class FSparseSnapshotTree; + +typedef void (^fbt_void_nsstring_sstree)(NSString *, FSparseSnapshotTree *); + +@interface FSparseSnapshotTree : NSObject + +- (id)findPath:(FPath *)path; +- (void)rememberData:(id)data onPath:(FPath *)path; +- (BOOL)forgetPath:(FPath *)path; +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func; +- (void)forEachChild:(fbt_void_nsstring_sstree)func; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m new file mode 100644 index 00000000..6219309f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSparseSnapshotTree.h" +#import "FChildrenNode.h" + +@interface FSparseSnapshotTree () { + id value; + NSMutableDictionary *children; +} + +@end + +@implementation FSparseSnapshotTree + +- (id)init { + self = [super init]; + if (self) { + value = nil; + children = nil; + } + return self; +} + +- (id)findPath:(FPath *)path { + if (value != nil) { + return [value getChild:path]; + } else if (![path isEmpty] && children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + FSparseSnapshotTree *childTree = children[childKey]; + if (childTree != nil) { + return [childTree findPath:path]; + } else { + return nil; + } + } else { + return nil; + } +} + +- (void)rememberData:(id)data onPath:(FPath *)path { + if ([path isEmpty]) { + value = data; + children = nil; + } else if (value != nil) { + value = [value updateChild:path withNewChild:data]; + } else { + if (children == nil) { + children = [[NSMutableDictionary alloc] init]; + } + + NSString *childKey = [path getFront]; + if (children[childKey] == nil) { + children[childKey] = [[FSparseSnapshotTree alloc] init]; + } + + FSparseSnapshotTree *child = children[childKey]; + path = [path popFront]; + [child rememberData:data onPath:path]; + } +} + +- (BOOL)forgetPath:(FPath *)path { + if ([path isEmpty]) { + value = nil; + children = nil; + return YES; + } else { + if (value != nil) { + if ([value isLeafNode]) { + // non-empty path at leaf. the path leads to nowhere + return NO; + } else { + id tmp = value; + value = nil; + + [tmp enumerateChildrenUsingBlock:^(NSString *key, + id node, BOOL *stop) { + [self rememberData:node onPath:[[FPath alloc] initWith:key]]; + }]; + + // we've cleared out the value and set children. Call ourself + // again to hit the next case + return [self forgetPath:path]; + } + } else if (children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + + if (children[childKey] != nil) { + FSparseSnapshotTree *child = children[childKey]; + BOOL safeToRemove = [child forgetPath:path]; + if (safeToRemove) { + [children removeObjectForKey:childKey]; + } + } + + if ([children count] == 0) { + children = nil; + return YES; + } else { + return NO; + } + } else { + return YES; + } + } +} + +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func { + if (value != nil) { + func(prefixPath, value); + } else { + [self forEachChild:^(NSString *key, FSparseSnapshotTree *tree) { + FPath *path = [prefixPath childFromString:key]; + [tree forEachTreeAtPath:path do:func]; + }]; + } +} + +- (void)forEachChild:(fbt_void_nsstring_sstree)func { + if (children != nil) { + for (NSString *key in children) { + FSparseSnapshotTree *tree = [children objectForKey:key]; + func(key, tree); + } + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h new file mode 100644 index 00000000..a9bd4d94 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FOperation; +@class FWriteTreeRef; +@protocol FNode; +@protocol FEventRegistration; +@class FQuerySpec; +@class FChildrenNode; +@class FTupleRemovedQueriesEvents; +@class FView; +@class FPath; +@class FCacheNode; +@class FPersistenceManager; + +@interface FSyncPoint : NSObject + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence; + +- (BOOL)isEmpty; + +/** + * Returns array of FEvent + */ +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; + +/** + * Returns array of FEvent + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache; + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query; + +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +/** + * Returns array of FViews + */ +- (NSArray *)queryViews; +- (id)completeServerCacheAtPath:(FPath *)path; +- (FView *)viewForQuery:(FQuerySpec *)query; +- (BOOL)viewExistsForQuery:(FQuerySpec *)query; +- (BOOL)hasCompleteView; +- (FView *)completeView; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m new file mode 100644 index 00000000..6496ae84 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m @@ -0,0 +1,302 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncPoint.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FDataEvent.h" +#import "FEmptyNode.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FView.h" +#import "FViewCache.h" +#import "FWriteTreeRef.h" + +/** + * SyncPoint represents a single location in a SyncTree with 1 or more event + * registrations, meaning we need to maintain 1 or more Views at this location + * to cache server data and raise appropriate events for server changes and user + * writes (set, transaction, update). + * + * It's responsible for: + * - Maintaining the set of 1 or more views necessary at this location (a + * SyncPoint with 0 views should be removed). + * - Proxying user / server operations to the views as appropriate (i.e. + * applyServerOverwrite, applyUserOverwrite, etc.) + */ +@interface FSyncPoint () +/** + * The Views being tracked at this location in the tree, stored as a map where + * the key is a queryParams and the value is the View for that query. + * + * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more + * is an odd use case). + * + * Maps NSString -> FView + */ +@property(nonatomic, strong) NSMutableDictionary *views; + +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@end + +@implementation FSyncPoint + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence { + self = [super init]; + if (self) { + self.persistenceManager = persistence; + self.views = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (BOOL)isEmpty { + return [self.views count] == 0; +} + +- (NSArray *)applyOperation:(id)operation + toView:(FView *)view + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FViewOperationResult *result = [view applyOperation:operation + writesCache:writesCache + serverCache:optCompleteServerCache]; + if (!view.query.loadsAllData) { + NSMutableSet *removed = [NSMutableSet set]; + NSMutableSet *added = [NSMutableSet set]; + [result.changes enumerateObjectsUsingBlock:^( + FChange *change, NSUInteger idx, BOOL *stop) { + if (change.type == FIRDataEventTypeChildAdded) { + [added addObject:change.childKey]; + } else if (change.type == FIRDataEventTypeChildRemoved) { + [removed addObject:change.childKey]; + } + }]; + if ([removed count] > 0 || [added count] > 0) { + [self.persistenceManager + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQuery:view.query]; + } + } + return result.events; +} + +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FQueryParams *queryParams = operation.source.queryParams; + if (queryParams != nil) { + FView *view = [self.views objectForKey:queryParams]; + NSAssert(view != nil, @"SyncTree gave us an op for an invalid query."); + return [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + } else { + NSMutableArray *events = [[NSMutableArray alloc] init]; + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *key, FView *view, BOOL *stop) { + NSArray *eventsForView = [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + [events addObjectsFromArray:eventsForView]; + }]; + return events; + } +} + +/** + * Add an event callback for the specified query + * Returns Array of FEvent events to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache { + NSAssert(self.views[query.params] == nil, @"Found view for query: %@", + query.params); + // TODO: make writesCache take flag for complete server node + id eventCache = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + serverCache.isFullyInitialized ? serverCache.node : nil]; + BOOL eventCacheComplete; + if (eventCache != nil) { + eventCacheComplete = YES; + } else { + eventCache = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren:serverCache + .node]; + eventCacheComplete = NO; + } + + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:eventCache + index:query.index]; + FCacheNode *eventCacheNode = + [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:eventCacheComplete + isFiltered:NO]; + FViewCache *viewCache = + [[FViewCache alloc] initWithEventCache:eventCacheNode + serverCache:serverCache]; + FView *view = [[FView alloc] initWithQuery:query + initialViewCache:viewCache]; + // If this is a non-default query we need to tell persistence our current + // view of the data + if (!query.loadsAllData) { + NSMutableSet *allKeys = [NSMutableSet set]; + [view.eventCache enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [allKeys addObject:key]; + }]; + [self.persistenceManager setTrackedQueryKeys:allKeys forQuery:query]; + } + self.views[query.params] = view; + return [self addEventRegistration:eventRegistration + forExistingViewForQuery:query]; +} + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query { + FView *view = self.views[query.params]; + NSAssert(view != nil, @"No view for query: %@", query); + [view addEventRegistration:eventRegistration]; + return [view initialEvents:eventRegistration]; +} + +/** + * Remove event callback(s). Return cancelEvents if a cancelError is specified. + * + * If query is the default query, we'll check all views for the specified + * eventRegistration. If eventRegistration is nil, we'll remove all callbacks + * for the specified view(s). + * + * @return FTupleRemovedQueriesEvents removed queries and any cancel events + */ +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + NSMutableArray *removedQueries = [[NSMutableArray alloc] init]; + __block NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + BOOL hadCompleteView = [self hasCompleteView]; + if ([query isDefault]) { + // When you do [ref removeObserverWithHandle:], we search all views for + // the registration to remove. + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *viewQueryParams, FView *view, + BOOL *stop) { + [cancelEvents + addObjectsFromArray:[view + removeEventRegistration:eventRegistration + cancelError:cancelError]]; + if ([view isEmpty]) { + [self.views removeObjectForKey:viewQueryParams]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + }]; + } else { + // remove the callback from the specific view + FView *view = [self.views objectForKey:query.params]; + if (view != nil) { + [cancelEvents addObjectsFromArray: + [view removeEventRegistration:eventRegistration + cancelError:cancelError]]; + + if ([view isEmpty]) { + [self.views removeObjectForKey:query.params]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + } + } + + if (hadCompleteView && ![self hasCompleteView]) { + // We removed our last complete view + [removedQueries addObject:[FQuerySpec defaultQueryAtPath:query.path]]; + } + + return [[FTupleRemovedQueriesEvents alloc] + initWithRemovedQueries:removedQueries + cancelEvents:cancelEvents]; +} + +- (NSArray *)queryViews { + __block NSMutableArray *filteredViews = [[NSMutableArray alloc] init]; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if (![view.query loadsAllData]) { + [filteredViews addObject:view]; + } + }]; + + return filteredViews; +} + +- (id)completeServerCacheAtPath:(FPath *)path { + __block id serverCache = nil; + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + serverCache = [view completeServerCacheFor:path]; + *stop = (serverCache != nil); + }]; + return serverCache; +} + +- (FView *)viewForQuery:(FQuerySpec *)query { + return [self.views objectForKey:query.params]; +} + +- (BOOL)viewExistsForQuery:(FQuerySpec *)query { + return [self viewForQuery:query] != nil; +} + +- (BOOL)hasCompleteView { + return [self completeView] != nil; +} + +- (FView *)completeView { + __block FView *completeView = nil; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if ([view.query loadsAllData]) { + completeView = view; + *stop = YES; + } + }]; + + return completeView; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h new file mode 100644 index 00000000..ef89774f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FListenProvider; +@protocol FNode; +@class FPath; +@protocol FEventRegistration; +@protocol FPersistedServerCache; +@class FQuerySpec; +@class FCompoundWrite; +@class FPersistenceManager; +@class FCompoundHash; +@protocol FClock; + +@protocol FSyncTreeHash + +- (NSString *)simpleHash; +- (FCompoundHash *)compoundHash; +- (BOOL)includeCompoundHash; + +@end + +@interface FSyncTree : NSObject + +- (id)initWithListenProvider:(FListenProvider *)provider; +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider; + +// These methods all return NSArray of FEvent +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock; +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData; +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren; +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges; +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId; +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced; +- (NSArray *)removeAllWrites; + +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m new file mode 100644 index 00000000..1c3e5146 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m @@ -0,0 +1,1042 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncTree.h" +#import "FAckUserWrite.h" +#import "FAtomicNumber.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundHash.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FImmutableTree.h" +#import "FKeepSyncedEventRegistration.h" +#import "FListenComplete.h" +#import "FListenProvider.h" +#import "FMerge.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncPoint.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FUtilities.h" +#import "FView.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" +#import "FWriteTreeRef.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +// Size after which we start including the compound hash +static const NSUInteger kFSizeThresholdForCompoundHash = 1024; + +@interface FListenContainer : NSObject + +@property(nonatomic, strong) FView *view; +@property(nonatomic, copy) fbt_nsarray_nsstring onComplete; + +@end + +@implementation FListenContainer + +- (instancetype)initWithView:(FView *)view + onComplete:(fbt_nsarray_nsstring)onComplete { + self = [super init]; + if (self != nil) { + self->_view = view; + self->_onComplete = onComplete; + } + return self; +} + +- (id)serverCache { + return self.view.serverCache; +} + +- (FCompoundHash *)compoundHash { + return [FCompoundHash fromNode:[self serverCache]]; +} + +- (NSString *)simpleHash { + return [[self serverCache] dataHash]; +} + +- (BOOL)includeCompoundHash { + return [FSnapshotUtilities estimateSerializedNodeSize:[self serverCache]] > + kFSizeThresholdForCompoundHash; +} + +@end + +@interface FSyncTree () + +/** + * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more + * views. + */ +@property(nonatomic, strong) FImmutableTree *syncPointTree; + +/** + * A tree of all pending user writes (user-initiated set, transactions, updates, + * etc) + */ +@property(nonatomic, strong) FWriteTree *pendingWriteTree; + +/** + * Maps tagId -> FTuplePathQueryParams + */ +@property(nonatomic, strong) NSMutableDictionary *tagToQueryMap; +@property(nonatomic, strong) NSMutableDictionary *queryToTagMap; +@property(nonatomic, strong) FListenProvider *listenProvider; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FAtomicNumber *queryTagCounter; +@property(nonatomic, strong) NSMutableSet *keepSyncedQueries; + +@end + +/** + * SyncTree is the central class for managing event callback registration, data + * caching, views (query processing), and event generation. There are typically + * two SyncTree instances for each Repo, one for the normal Firebase data, and + * one for the .info data. + * + * It has a number of responsibilities, including: + * - Tracking all user event callbacks (registered via addEventRegistration: + * and removeEventRegistration:). + * - Applying and caching data changes for user setValue:, + * runTransactionBlock:, and updateChildValues: calls + * (applyUserOverwriteAtPath:, applyUserMergeAtPath:). + * - Applying and caching data changes for server data changes + * (applyServerOverwriteAtPath:, applyServerMergeAtPath:). + * - Generating user-facing events for server and user changes (all of the + * apply* methods return the set of events that need to be raised as a result). + * - Maintaining the appropriate set of server listens to ensure we are always + * subscribed to the correct set of paths and queries to satisfy the current set + * of user event callbacks (listens are started/stopped using the provided + * listenProvider). + * + * NOTE: Although SyncTree tracks event callbacks and calculates events to + * raise, the actual events are returned to the caller rather than raised + * synchronously. + */ +@implementation FSyncTree + +- (id)initWithListenProvider:(FListenProvider *)provider { + return [self initWithPersistenceManager:nil listenProvider:provider]; +} + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider { + self = [super init]; + if (self) { + self.syncPointTree = [FImmutableTree empty]; + self.pendingWriteTree = [[FWriteTree alloc] init]; + self.tagToQueryMap = [[NSMutableDictionary alloc] init]; + self.queryToTagMap = [[NSMutableDictionary alloc] init]; + self.listenProvider = provider; + self.persistenceManager = persistenceManager; + self.queryTagCounter = [[FAtomicNumber alloc] init]; + self.keepSyncedQueries = [NSMutableSet set]; + } + return self; +} + +#pragma mark - +#pragma mark Apply Operations + +/** + * Apply data changes for a user-generated setValue: runTransactionBlock: + * updateChildValues:, etc. + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + // Record pending write + [self.pendingWriteTree addOverwriteAtPath:path + newData:newData + writeId:writeId + isVisible:visible]; + if (!visible) { + return @[]; + } else { + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource userInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply the data from a user-generated updateChildValues: call + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + // Record pending merge + [self.pendingWriteTree addMergeAtPath:path + changedChildren:changedChildren + writeId:writeId]; + + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource userInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Acknowledge a pending user write that was previously registered with + * applyUserOverwriteAtPath: or applyUserMergeAtPath: + * TODO[offline]: Taking a serverClock here is awkward, but server values are + * awkward. :-( + * @return NSArray of FEvent to raise. + */ +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock { + FWriteRecord *write = [self.pendingWriteTree writeForId:writeId]; + BOOL needToReevaluate = [self.pendingWriteTree removeWriteId:writeId]; + if (write.visible) { + if (persist) { + [self.persistenceManager removeUserWrite:writeId]; + } + if (!revert) { + NSDictionary *serverValues = + [FServerValues generateServerValues:clock]; + if ([write isOverwrite]) { + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withSyncTree:self + atPath:write.path + serverValues:serverValues]; + [self.persistenceManager applyUserWrite:resolvedNode + toServerCacheAtPath:write.path]; + } else { + FCompoundWrite *resolvedMerge = [FServerValues + resolveDeferredValueCompoundWrite:write.merge + withSyncTree:self + atPath:write.path + serverValues:serverValues]; + [self.persistenceManager applyUserMerge:resolvedMerge + toServerCacheAtPath:write.path]; + } + } + } + if (!needToReevaluate) { + return @[]; + } else { + __block FImmutableTree *affectedTree = [FImmutableTree empty]; + if (write.isOverwrite) { + affectedTree = [affectedTree setValue:@YES atPath:[FPath empty]]; + } else { + [write.merge + enumerateWrites:^(FPath *path, id node, BOOL *stop) { + affectedTree = [affectedTree setValue:@YES atPath:path]; + }]; + } + FAckUserWrite *operation = + [[FAckUserWrite alloc] initWithPath:write.path + affectedTree:affectedTree + revert:revert]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply new server data for the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData { + [self.persistenceManager + updateServerCacheWithNode:newData + forQuery:[FQuerySpec defaultQueryAtPath:path]]; + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource serverInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Applied new server data to be merged in at the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren { + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource serverInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + // Removed view, so it's safe to just ignore this update + return @[]; + } else { + // This could be for any "complete" (unfiltered) view, and if there is + // more than one complete view, they should each have the same cache so + // it doesn't matter which one we use. + FView *view = [syncPoint completeView]; + if (view != nil) { + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyServerOverwriteAtPath:path newData:serverNode]; + } else { + // There doesn't exist a view for this update, so it was removed and + // it's safe to just ignore this range merge + return @[]; + } + } +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyListenCompleteAtPath:(FPath *)path { + [self.persistenceManager + setQueryComplete:[FQuerySpec defaultQueryAtPath:path]]; + id operation = [[FListenComplete alloc] + initWithSource:[FOperationSource serverInstance] + path:path]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedListenCompleteAtPath:(FPath *)path + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + [self.persistenceManager setQueryComplete:query]; + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + id op = [[FListenComplete alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath]; + return [self applyTaggedOperation:op atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Internal helper method to apply tagged operation + */ +- (NSArray *)applyTaggedOperation:(id)operation + atPath:(FPath *)path { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + return [syncPoint applyOperation:operation + writesCache:writesCache + serverCache:nil]; +} + +/** + * Apply new server data for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + FQuerySpec *queryToOverwrite = + relativePath.isEmpty ? query : [FQuerySpec defaultQueryAtPath:path]; + [self.persistenceManager updateServerCacheWithNode:newData + forQuery:queryToOverwrite]; + FOverwrite *operation = [[FOverwrite alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + snap:newData]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // Query must have been removed already + return @[]; + } +} + +/** + * Apply server data to be merged in for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = [[FMerge alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + children:changedChildren]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + NSAssert([path isEqual:query.path], + @"Tagged update path and query path must match"); + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FView *view = [syncPoint viewForQuery:query]; + NSAssert(view != nil, + @"Missing view for query tag that we're tracking"); + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyTaggedQueryOverwriteAtPath:path + newData:serverNode + tagId:tagId]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Add an event callback for the specified query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + FPath *path = query.path; + + __block BOOL foundAncestorDefaultView = NO; + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + foundAncestorDefaultView = + foundAncestorDefaultView || [syncPoint hasCompleteView]; + return !foundAncestorDefaultView; + }]; + + [self.persistenceManager setQueryActive:query]; + + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + syncPoint = [[FSyncPoint alloc] + initWithPersistenceManager:self.persistenceManager]; + self.syncPointTree = [self.syncPointTree setValue:syncPoint + atPath:path]; + } + + BOOL viewAlreadyExists = [syncPoint viewExistsForQuery:query]; + NSArray *events; + if (viewAlreadyExists) { + events = [syncPoint addEventRegistration:eventRegistration + forExistingViewForQuery:query]; + } else { + if (![query loadsAllData]) { + // We need to track a tag for this query + NSAssert(self.queryToTagMap[query] == nil, + @"View does not exist, but we have a tag"); + NSNumber *tagId = [self.queryTagCounter getAndIncrement]; + self.queryToTagMap[query] = tagId; + self.tagToQueryMap[tagId] = query; + } + + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + FCacheNode *serverCache = [self serverCacheForQuery:query]; + events = [syncPoint addEventRegistration:eventRegistration + forNonExistingViewForQuery:query + writesCache:writesCache + serverCache:serverCache]; + + // There was no view and no default listen + if (!foundAncestorDefaultView) { + FView *view = [syncPoint viewForQuery:query]; + NSMutableArray *mutableEvents = [events mutableCopy]; + [mutableEvents + addObjectsFromArray:[self setupListenerOnQuery:query + view:view]]; + events = mutableEvents; + } + } + + return events; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + __block id serverCacheNode = nil; + + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathToSyncPoint + to:query.path]; + serverCacheNode = + [syncPoint completeServerCacheAtPath:relativePath]; + return serverCacheNode == nil; + }]; + + FCacheNode *serverCache; + if (serverCacheNode != nil) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + FCacheNode *persistenceServerCache = + [self.persistenceManager serverCacheForQuery:query]; + if (persistenceServerCache.isFullyInitialized) { + serverCache = persistenceServerCache; + } else { + serverCacheNode = [FEmptyNode emptyNode]; + + FImmutableTree *subtree = + [self.syncPointTree subtreeAtPath:query.path]; + [subtree + forEachChild:^(NSString *childKey, FSyncPoint *childSyncPoint) { + id completeCache = + [childSyncPoint completeServerCacheAtPath:[FPath empty]]; + if (completeCache) { + serverCacheNode = + [serverCacheNode updateImmediateChild:childKey + withNewChild:completeCache]; + } + }]; + // Fill the node with any available children we have + [persistenceServerCache.node + enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (![serverCacheNode hasChild:key]) { + serverCacheNode = + [serverCacheNode updateImmediateChild:key + withNewChild:node]; + } + }]; + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:NO + isFiltered:NO]; + } + } + + return serverCache; +} + +/** + * Remove event callback(s). + * + * If query is the default query, we'll check all queries for the specified + * eventRegistration. If eventRegistration is null, we'll remove all callbacks + * for the specified query/queries. + * + * @param eventRegistration if nil, all callbacks are removed + * @param cancelError If provided, appropriate cancel events will be returned + * @return NSArray of FEvent to raise. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + // Find the syncPoint first. Then deal with whether or not it has matching + // listeners + FPath *path = query.path; + FSyncPoint *maybeSyncPoint = [self.syncPointTree valueAtPath:path]; + NSArray *cancelEvents = @[]; + + // A removal on a default query affects all queries at that location. A + // removal on an indexed query, even one without other query constraints, + // does *not* affect all queries at that location. So this check must be for + // 'default', and not loadsAllData: + if (maybeSyncPoint && + ([query isDefault] || [maybeSyncPoint viewExistsForQuery:query])) { + FTupleRemovedQueriesEvents *removedAndEvents = + [maybeSyncPoint removeEventRegistration:eventRegistration + forQuery:query + cancelError:cancelError]; + if ([maybeSyncPoint isEmpty]) { + self.syncPointTree = [self.syncPointTree removeValueAtPath:path]; + } + NSArray *removed = removedAndEvents.removedQueries; + cancelEvents = removedAndEvents.cancelEvents; + + // We may have just removed one of many listeners and can short-circuit + // this whole process We may also not have removed a default listener, + // in which case all of the descendant listeners should already be + // properly set up. + // + // Since indexed queries can shadow if they don't have other query + // constraints, check for loadsAllData: instead of isDefault: + NSUInteger defaultQueryIndex = [removed + indexOfObjectPassingTest:^BOOL(FQuerySpec *q, NSUInteger idx, + BOOL *stop) { + return [q loadsAllData]; + }]; + BOOL removingDefault = defaultQueryIndex != NSNotFound; + [removed enumerateObjectsUsingBlock:^(FQuerySpec *query, NSUInteger idx, + BOOL *stop) { + [self.persistenceManager setQueryInactive:query]; + }]; + NSNumber *covered = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *relativePath, + FSyncPoint *parentSyncPoint) { + return + [NSNumber numberWithBool:[parentSyncPoint hasCompleteView]]; + }]; + + if (removingDefault && ![covered boolValue]) { + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // There are potentially child listeners. Determine what if any + // listens we need to send before executing the removal + if (![subtree isEmpty]) { + // We need to fold over our subtree and collect the listeners to + // send + NSArray *newViews = + [self collectDistinctViewsForSubTree:subtree]; + + // Ok, we've collected all the listens we need. Set them up. + [newViews enumerateObjectsUsingBlock:^( + FView *view, NSUInteger idx, BOOL *stop) { + FQuerySpec *newQuery = view.query; + FListenContainer *listenContainer = + [self createListenerForView:view]; + self.listenProvider.startListening( + [self queryForListening:newQuery], + [self tagForQuery:newQuery], listenContainer, + listenContainer.onComplete); + }]; + } else { + // There's nothing below us, so nothing we need to start + // listening on + } + } + + // If we removed anything and we're not covered by a higher up listen, + // we need to stop listening on this query. The above block has us + // covered in terms of making sure we're set up on listens lower in the + // tree. Also, note that if we have a cancelError, it's already been + // removed at the provider level. + if (![covered boolValue] && [removed count] > 0 && cancelError == nil) { + // If we removed a default, then we weren't listening on any of the + // other queries here. Just cancel the one default. Otherwise, we + // need to iterate through and cancel each individual query + if (removingDefault) { + // We don't tag default listeners + self.listenProvider.stopListening( + [self queryForListening:query], nil); + } else { + [removed + enumerateObjectsUsingBlock:^(FQuerySpec *queryToRemove, + NSUInteger idx, BOOL *stop) { + NSNumber *tagToRemove = + [self.queryToTagMap objectForKey:queryToRemove]; + self.listenProvider.stopListening( + [self queryForListening:queryToRemove], tagToRemove); + }]; + } + } + // Now, clear all the tags we're tracking for the removed listens. + [self removeTags:removed]; + } else { + // No-op, this listener must've been already removed + } + return cancelEvents; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced { + // Only do something if we actually need to add/remove an event registration + if (keepSynced && ![self.keepSyncedQueries containsObject:query]) { + [self addEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query]; + [self.keepSyncedQueries addObject:query]; + } else if (!keepSynced && [self.keepSyncedQueries containsObject:query]) { + [self removeEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query + cancelError:nil]; + [self.keepSyncedQueries removeObject:query]; + } +} + +- (NSArray *)removeAllWrites { + [self.persistenceManager removeAllUserWrites]; + NSArray *removedWrites = [self.pendingWriteTree removeAllWrites]; + if (removedWrites.count > 0) { + FImmutableTree *affectedTree = + [[FImmutableTree empty] setValue:@YES atPath:[FPath empty]]; + return [self applyOperationToSyncPoints:[[FAckUserWrite alloc] + initWithPath:[FPath empty] + affectedTree:affectedTree + revert:YES]]; + } else { + return @[]; + } +} + +/** + * Returns a complete cache, if we have one, of the data at a particular path. + * The location must have a listener above it, but as this is only used by + * transaction code, that should always be the case anyways. + * + * Note: this method will *include* hidden writes from transaction with + * applyLocally set to false. + * @param path The path to the data we want + * @param writeIdsToExclude A specific set to be excluded + */ +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + BOOL includeHiddenSets = YES; + FWriteTree *writeTree = self.pendingWriteTree; + id serverCache = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *pathSoFar, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathSoFar to:path]; + id serverCache = + [syncPoint completeServerCacheAtPath:relativePath]; + if (serverCache) { + return serverCache; + } else { + return nil; + } + }]; + return [writeTree calculateCompleteEventCacheAtPath:path + completeServerCache:serverCache + excludeWriteIds:writeIdsToExclude + includeHiddenWrites:includeHiddenSets]; +} + +#pragma mark - +#pragma mark Private Methods +/** + * This collapses multiple unfiltered views into a single view, since we only + * need a single listener for them. + * @return NSArray of FView + */ +- (NSArray *)collectDistinctViewsForSubTree:(FImmutableTree *)subtree { + return [subtree foldWithBlock:^NSArray *(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (maybeChildSyncPoint && [maybeChildSyncPoint hasCompleteView]) { + FView *completeView = [maybeChildSyncPoint completeView]; + return @[ completeView ]; + } else { + // No complete view here, flatten any deeper listens into an array + NSMutableArray *views = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint) { + views = [[maybeChildSyncPoint queryViews] mutableCopy]; + } + [childMap enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, NSArray *childViews, BOOL *stop) { + [views addObjectsFromArray:childViews]; + }]; + return views; + } + }]; +} + +/** + * @param queries NSArray of FQuerySpec + */ +- (void)removeTags:(NSArray *)queries { + [queries enumerateObjectsUsingBlock:^(FQuerySpec *removedQuery, + NSUInteger idx, BOOL *stop) { + if (![removedQuery loadsAllData]) { + // We should have a tag for this + NSNumber *removedQueryTag = self.queryToTagMap[removedQuery]; + [self.queryToTagMap removeObjectForKey:removedQuery]; + [self.tagToQueryMap removeObjectForKey:removedQueryTag]; + } + }]; +} + +- (FQuerySpec *)queryForListening:(FQuerySpec *)query { + if (query.loadsAllData && !query.isDefault) { + // We treat queries that load all data as default queries + return [FQuerySpec defaultQueryAtPath:query.path]; + } else { + return query; + } +} + +/** + * For a given new listen, manage the de-duplication of outstanding + * subscriptions. + * @return NSArray of FEvent events to support synchronous data sources + */ +- (NSArray *)setupListenerOnQuery:(FQuerySpec *)query view:(FView *)view { + FPath *path = query.path; + NSNumber *tagId = [self tagForQuery:query]; + FListenContainer *listenContainer = [self createListenerForView:view]; + + NSArray *events = self.listenProvider.startListening( + [self queryForListening:query], tagId, listenContainer, + listenContainer.onComplete); + + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // The root of this subtree has our query. We're here because we definitely + // need to send a listen for that, but we may need to shadow other listens + // as well. + if (tagId != nil) { + NSAssert(![subtree.value hasCompleteView], + @"If we're adding a query, it shouldn't be shadowed"); + } else { + // Shadow everything at or below this location, this is a default + // listener. + NSArray *queriesToStop = + [subtree foldWithBlock:^id(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (![relativePath isEmpty] && maybeChildSyncPoint != nil && + [maybeChildSyncPoint hasCompleteView]) { + return @[ [maybeChildSyncPoint completeView].query ]; + } else { + // No default listener here, flatten any deeper queries into + // an array + NSMutableArray *queries = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint != nil) { + for (FView *view in [maybeChildSyncPoint queryViews]) { + [queries addObject:view.query]; + } + } + [childMap + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, NSArray *childQueries, BOOL *stop) { + [queries addObjectsFromArray:childQueries]; + }]; + return queries; + } + }]; + for (FQuerySpec *queryToStop in queriesToStop) { + self.listenProvider.stopListening( + [self queryForListening:queryToStop], + [self tagForQuery:queryToStop]); + } + } + return events; +} + +- (FListenContainer *)createListenerForView:(FView *)view { + FQuerySpec *query = view.query; + NSNumber *tagId = [self tagForQuery:query]; + + FListenContainer *listenContainer = [[FListenContainer alloc] + initWithView:view + onComplete:^(NSString *status) { + if ([status isEqualToString:@"ok"]) { + if (tagId != nil) { + return [self applyTaggedListenCompleteAtPath:query.path + tagId:tagId]; + } else { + return [self applyListenCompleteAtPath:query.path]; + } + } else { + // If a listen failed, kill all of the listeners here, not just + // the one that triggered the error. Note that this may need to + // be scoped to just this listener if we change permissions on + // filtered children + NSError *error = [FUtilities errorForStatus:status + andReason:nil]; + FFWarn(@"I-RDB038012", @"Listener at %@ failed: %@", query.path, + status); + return [self removeEventRegistration:nil + forQuery:query + cancelError:error]; + } + }]; + + return listenContainer; +} + +/** + * @return The query associated with the given tag, if we have one + */ +- (FQuerySpec *)queryForTag:(NSNumber *)tagId { + return self.tagToQueryMap[tagId]; +} + +/** + * @return The tag associated with the given query + */ +- (NSNumber *)tagForQuery:(FQuerySpec *)query { + return self.queryToTagMap[query]; +} + +#pragma mark - +#pragma mark applyOperation Helpers + +/** +* A helper method that visits all descendant and ancestor SyncPoints, applying +the operation. +* +* NOTES: +* - Descendant SyncPoints will be visited first (since we raise events +depth-first). + +* - We call applyOperation: on each SyncPoint passing three things: +* 1. A version of the Operation that has been made relative to the SyncPoint +location. +* 2. A WriteTreeRef of any writes we have cached at the SyncPoint location. +* 3. A snapshot Node with cached server data, if we have it. + +* - We concatenate all of the events returned by each SyncPoint and return the +result. +* +* @return Array of FEvent +*/ +- (NSArray *)applyOperationToSyncPoints:(id)operation { + return [self applyOperationHelper:operation + syncPointTree:self.syncPointTree + serverCache:nil + writesCache:[self.pendingWriteTree + childWritesForPath:[FPath empty]]]; +} + +/** + * Recursive helper for applyOperationToSyncPoints_ + */ +- (NSArray *)applyOperationHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + if ([operation.path isEmpty]) { + return [self applyOperationDescendantsHelper:operation + syncPointTree:syncPointTree + serverCache:serverCache + writesCache:writesCache]; + } else { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + if (serverCache == nil && syncPoint != nil) { + serverCache = [syncPoint completeServerCacheAtPath:[FPath empty]]; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSString *childKey = [operation.path getFront]; + id childOperation = [operation operationForChild:childKey]; + FImmutableTree *childTree = [syncPointTree.children get:childKey]; + if (childTree != nil && childOperation != nil) { + id childServerCache = + serverCache ? [serverCache getImmediateChild:childKey] : nil; + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + [events + addObjectsFromArray:[self + applyOperationHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + + if (syncPoint) { + [events addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:serverCache]]; + } + + return events; + } +} + +/** + * Recursive helper for applyOperationToSyncPoints: + */ +- (NSArray *)applyOperationDescendantsHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + id resolvedServerCache; + if (serverCache == nil & syncPoint != nil) { + resolvedServerCache = + [syncPoint completeServerCacheAtPath:[FPath empty]]; + } else { + resolvedServerCache = serverCache; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + [syncPointTree.children enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, + BOOL *stop) { + id childServerCache = nil; + if (resolvedServerCache != nil) { + childServerCache = [resolvedServerCache getImmediateChild:childKey]; + } + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + id childOperation = [operation operationForChild:childKey]; + if (childOperation != nil) { + [events addObjectsFromArray: + [self applyOperationDescendantsHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + }]; + + if (syncPoint) { + [events + addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:resolvedServerCache]]; + } + + return events; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h new file mode 100644 index 00000000..435fb6a1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@class FCompoundWrite; +@protocol FNode; + +@interface FWriteRecord : NSObject + +- initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible; +- initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId; + +@property(nonatomic, readonly) NSInteger writeId; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id overwrite; +/** + * Maps NSString -> id + */ +@property(nonatomic, strong, readonly) FCompoundWrite *merge; +@property(nonatomic, readonly) BOOL visible; + +- (BOOL)isMerge; +- (BOOL)isOverwrite; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m new file mode 100644 index 00000000..be1816e1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m @@ -0,0 +1,139 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteRecord.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" + +@interface FWriteRecord () +@property(nonatomic, readwrite) NSInteger writeId; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) id overwrite; +@property(nonatomic, strong, readwrite) FCompoundWrite *merge; +@property(nonatomic, readwrite) BOOL visible; +@end + +@implementation FWriteRecord + +- (id)initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible { + self = [super init]; + if (self) { + self.path = path; + if (overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as overwrite parameter to an " + @"overwrite write record"]; + } + self.overwrite = overwrite; + self.merge = nil; + self.writeId = writeId; + self.visible = isVisible; + } + return self; +} + +- (id)initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId { + self = [super init]; + if (self) { + self.path = path; + if (merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as merge parameter to an merge " + @"write record"]; + } + self.overwrite = nil; + self.merge = merge; + self.writeId = writeId; + self.visible = YES; + } + return self; +} + +- (id)overwrite { + if (self->_overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get overwrite for merge write record!"]; + } + return self->_overwrite; +} + +- (FCompoundWrite *)compoundWrite { + if (self->_merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get merge for overwrite write record!"]; + } + return self->_merge; +} + +- (BOOL)isMerge { + return self->_merge != nil; +} + +- (BOOL)isOverwrite { + return self->_overwrite != nil; +} + +- (NSString *)description { + if (self.isOverwrite) { + return + [NSString stringWithFormat:@"FWriteRecord { writeId = %lu, path = " + @"%@, overwrite = %@, visible = %d }", + (unsigned long)self.writeId, self.path, + self.overwrite, self.visible]; + } else { + return [NSString + stringWithFormat: + @"FWriteRecord { writeId = %lu, path = %@, merge = %@ }", + (unsigned long)self.writeId, self.path, self.merge]; + } +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[self class]]) { + return NO; + } + FWriteRecord *other = (FWriteRecord *)object; + if (self->_writeId != other->_writeId) + return NO; + if (self->_path != other->_path && ![self->_path isEqual:other->_path]) + return NO; + if (self->_overwrite != other->_overwrite && + ![self->_overwrite isEqual:other->_overwrite]) + return NO; + if (self->_merge != other->_merge && ![self->_merge isEqual:other->_merge]) + return NO; + if (self->_visible != other->_visible) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self->_writeId * 17; + hash = hash * 31 + self->_path.hash; + hash = hash * 31 + self->_overwrite.hash; + hash = hash * 31 + self->_merge.hash; + hash = hash * 31 + ((self->_visible) ? 1 : 0); + return hash; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h new file mode 100644 index 00000000..178946b2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@protocol FNode; +@class FCompoundWrite; +@class FWriteTreeRef; +@class FChildrenNode; +@class FNamedNode; +@class FWriteRecord; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTree : NSObject + +- (FWriteTreeRef *)childWritesForPath:(FPath *)path; +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (BOOL)removeWriteId:(NSInteger)writeId; +- (NSArray *)removeAllWrites; +- (FWriteRecord *)writeForId:(NSInteger)writeId; + +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites; + +- (id)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap:(id)existingEventSnap + existingServerSnap:(id)existingServerSnap; + +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)path + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m new file mode 100644 index 00000000..d8592c04 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m @@ -0,0 +1,577 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTree.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FImmutableTree.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTreeRef.h" + +@interface FWriteTree () +/** + * A tree tracking the results of applying all visible writes. This does not + * include transactions with applyLocally=false or writes that are completely + * shadowed by other writes. Contains id as values. + */ +@property(nonatomic, strong) FCompoundWrite *visibleWrites; +/** + * A list of pending writes, regardless of visibility and shadowed-ness. Used to + * calcuate arbitrary sets of the changed data, such as hidden writes (from + * transactions) or changes with certain writes excluded (also used by + * transactions). Contains FWriteRecords. + */ +@property(nonatomic, strong) NSMutableArray *allWrites; +@property(nonatomic) NSInteger lastWriteId; +@end + +/** + * FWriteTree tracks all pending user-initiated writes and has methods to + * calcuate the result of merging them with underlying server data (to create + * "event cache" data). Pending writes are added with addOverwriteAtPath: and + * addMergeAtPath: and removed with removeWriteId:. + */ +@implementation FWriteTree + +@synthesize allWrites; +@synthesize lastWriteId; + +- (id)init { + self = [super init]; + if (self) { + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [[NSMutableArray alloc] init]; + self.lastWriteId = -1; + } + return self; +} + +/** + * Create a new WriteTreeRef for the given path. For use with a new sync point + * at the given path. + */ +- (FWriteTreeRef *)childWritesForPath:(FPath *)path { + return [[FWriteTreeRef alloc] initWithPath:path writeTree:self]; +} + +/** + * Record a new overwrite from user code. + * @param visible Is set to false by some transactions. It should be excluded + * from event caches. + */ +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older write on top of a newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + overwrite:newData + writeId:writeId + visible:visible]; + [self.allWrites addObject:record]; + + if (visible) { + self.visibleWrites = [self.visibleWrites addWrite:newData atPath:path]; + } + + self.lastWriteId = writeId; +} + +/** + * Record a new merge from user code. + * @param changedChildren maps NSString -> id + */ +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older merge on top of newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + merge:changedChildren + writeId:writeId]; + [self.allWrites addObject:record]; + + self.visibleWrites = [self.visibleWrites addCompoundWrite:changedChildren + atPath:path]; + self.lastWriteId = writeId; +} + +- (FWriteRecord *)writeForId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + return write.writeId == writeId; + }]; + return (index == NSNotFound) ? nil : self.allWrites[index]; +} + +/** + * Remove a write (either an overwrite or merge) that has been successfully + * acknowledged by the server. Recalculates the tree if necessary. We return the + * path of the write and whether it may have been visible, meaning views need to + * reevaluate. + * + * @return YES if the write may have been visible (meaning we'll need to + * reevaluate / raise events as a result). + */ +- (BOOL)removeWriteId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + if (record.writeId == writeId) { + return YES; + } else { + return NO; + } + }]; + NSAssert(index != NSNotFound, + @"[FWriteTree removeWriteId:] called with nonexistent writeId."); + FWriteRecord *writeToRemove = self.allWrites[index]; + [self.allWrites removeObjectAtIndex:index]; + + BOOL removedWriteWasVisible = writeToRemove.visible; + BOOL removedWriteOverlapsWithOtherWrites = NO; + NSInteger i = [self.allWrites count] - 1; + + while (removedWriteWasVisible && i >= 0) { + FWriteRecord *currentWrite = [self.allWrites objectAtIndex:i]; + if (currentWrite.visible) { + if (i >= index && [self record:currentWrite + containsPath:writeToRemove.path]) { + // The removed write was completely shadowed by a subsequent + // write. + removedWriteWasVisible = NO; + } else if ([writeToRemove.path contains:currentWrite.path]) { + // Either we're covering some writes or they're covering part of + // us (depending on which came first). + removedWriteOverlapsWithOtherWrites = YES; + } + } + i--; + } + + if (!removedWriteWasVisible) { + return NO; + } else if (removedWriteOverlapsWithOtherWrites) { + // There's some shadowing going on. Just rebuild the visible writes from + // scratch. + [self resetTree]; + return YES; + } else { + // There's no shadowing. We can safely just remove the write(s) from + // visibleWrites. + if ([writeToRemove isOverwrite]) { + self.visibleWrites = + [self.visibleWrites removeWriteAtPath:writeToRemove.path]; + } else { + FCompoundWrite *merge = writeToRemove.merge; + [merge enumerateWrites:^(FPath *path, id node, BOOL *stop) { + self.visibleWrites = [self.visibleWrites + removeWriteAtPath:[writeToRemove.path child:path]]; + }]; + } + return YES; + } +} + +- (NSArray *)removeAllWrites { + NSArray *writes = self.allWrites; + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [NSMutableArray array]; + return writes; +} + +/** + * @return A complete snapshot for the given path if there's visible write data + * at that path, else nil. No server data is considered. + */ +- (id)completeWriteDataAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * Given optional, underlying server data, and an optional set of constraints + * (exclude some sets, include hidden writes), attempt to calculate a complete + * snapshot for the given path + * @param includeHiddenWrites Defaults to false, whether or not to layer on + * writes with visible set to false + */ +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites { + if (writeIdsToExclude == nil && !includeHiddenWrites) { + id shadowingNode = + [self.visibleWrites completeNodeAtPath:treePath]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + // No cache here. Can't claim complete knowledge. + FCompoundWrite *subMerge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (subMerge.isEmpty) { + return completeServerCache; + } else if (completeServerCache == nil && + ![subMerge hasCompleteWriteAtPath:[FPath empty]]) { + // We wouldn't have a complete snapshot since there's no + // underlying data and no complete shadow + return nil; + } else { + id layeredCache = completeServerCache != nil + ? completeServerCache + : [FEmptyNode emptyNode]; + return [subMerge applyToNode:layeredCache]; + } + } + } else { + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (!includeHiddenWrites && merge.isEmpty) { + return completeServerCache; + } else { + // If the server cache is null and we don't have a complete cache, + // we need to return nil + if (!includeHiddenWrites && completeServerCache == nil && + ![merge hasCompleteWriteAtPath:[FPath empty]]) { + return nil; + } else { + BOOL (^filter)(FWriteRecord *) = ^(FWriteRecord *record) { + return (BOOL)( + (record.visible || includeHiddenWrites) && + (writeIdsToExclude == nil || + ![writeIdsToExclude + containsObject: + [NSNumber numberWithInteger:record.writeId]]) && + ([record.path contains:treePath] || + [treePath contains:record.path])); + }; + FCompoundWrite *mergeAtPath = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:filter + treeRoot:treePath]; + id layeredCache = completeServerCache + ? completeServerCache + : [FEmptyNode emptyNode]; + return [mergeAtPath applyToNode:layeredCache]; + } + } + } +} + +/** + * With optional, underlying server data, attempt to return a children node of + * children that we have complete data for. Used when creating new views, to + * pre-fill their complete event children snapshot. + */ +- (FChildrenNode *)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren { + __block id completeChildren = [FEmptyNode emptyNode]; + id topLevelSet = [self.visibleWrites completeNodeAtPath:treePath]; + if (topLevelSet != nil) { + if (![topLevelSet isLeafNode]) { + // We're shadowing everything. Return the children. + FChildrenNode *topChildrenNode = topLevelSet; + [topChildrenNode enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + completeChildren = [completeChildren updateImmediateChild:key + withNewChild:node]; + }]; + } + return completeChildren; + } else { + // Layer any children we have on top of this + // We know we don't have a top-level set, so just enumerate existing + // children, and apply any updates + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + [completeServerChildren enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FCompoundWrite *childMerge = + [merge childCompoundWriteAtPath:[[FPath alloc] initWith:key]]; + id newChildNode = [childMerge applyToNode:node]; + completeChildren = + [completeChildren updateImmediateChild:key + withNewChild:newChildNode]; + }]; + // Add any complete children we have from the set. + for (FNamedNode *node in merge.completeChildren) { + completeChildren = + [completeChildren updateImmediateChild:node.name + withNewChild:node.node]; + } + return completeChildren; + } +} + +/** + * Given that the underlying server data has updated, determine what, if + * anything, needs to be applied to the event cache. + * + * Possibilities + * + * 1. No write are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some write is completely shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events .. + * + * Either existingEventSnap or existingServerSnap must exist. + */ +- (id)calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + NSAssert(existingEventSnap != nil || existingServerSnap != nil, + @"Either existingEventSnap or existingServerSanp must exist."); + + FPath *path = [treePath child:childPath]; + if ([self.visibleWrites hasCompleteWriteAtPath:path]) { + // At this point we can probably guarantee that we're in case 2, meaning + // no events May need to check visibility while doing the + // findRootMostValueAndPath call + return nil; + } else { + // This could be more efficient if the serverNode + updates doesn't + // change the eventSnap However this is tricky to find out, since user + // updates don't necessary change the server snap, e.g. priority updates + // on empty nodes, or deep deletes. Another special case is if the + // server adds nodes, but doesn't change any existing writes. It is + // therefore not enough to only check if the updates change the + // serverNode. Maybe check if the merge tree contains these special + // cases and only do a full overwrite in that case? + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + if (childMerge.isEmpty) { + // We're not shadowing at all. Case 1 + return [existingServerSnap getChild:childPath]; + } else { + return [childMerge + applyToNode:[existingServerSnap getChild:childPath]]; + } + } +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + FPath *path = [treePath childFromString:childKey]; + id shadowingNode = [self.visibleWrites completeNodeAtPath:path]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + if ([existingServerCache isCompleteForChild:childKey]) { + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + return [childMerge applyToNode:[existingServerCache.node + getImmediateChild:childKey]]; + } else { + return nil; + } + } +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns null if + * there is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that were outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)treePath + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + __block id toIterate; + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + id shadowingNode = [merge completeNodeAtPath:[FPath empty]]; + if (shadowingNode != nil) { + toIterate = shadowingNode; + } else if (completeServerData != nil) { + toIterate = [merge applyToNode:completeServerData]; + } else { + return nil; + } + + __block NSString *currentNextKey = nil; + __block id currentNextNode = nil; + [toIterate enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if ([index compareKey:key + andNode:node + toOtherKey:post.name + andNode:post.node + reverse:reverse] > NSOrderedSame && + (!currentNextKey || [index compareKey:key + andNode:node + toOtherKey:currentNextKey + andNode:currentNextNode + reverse:reverse] < NSOrderedSame)) { + currentNextKey = key; + currentNextNode = node; + } + }]; + + if (currentNextKey != nil) { + return [FNamedNode nodeWithName:currentNextKey node:currentNextNode]; + } else { + return nil; + } +} + +#pragma mark - +#pragma mark Private Methods + +- (BOOL)record:(FWriteRecord *)record containsPath:(FPath *)path { + if ([record isOverwrite]) { + return [record.path contains:path]; + } else { + __block BOOL contains = NO; + [record.merge + enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + contains = [[record.path child:childPath] contains:path]; + *stop = contains; + }]; + return contains; + } +} + +/** + * Re-layer the writes and merges into a tree so we can efficiently calculate + * event snapshots + */ +- (void)resetTree { + self.visibleWrites = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:[FWriteTree defaultFilter] + treeRoot:[FPath empty]]; + if ([self.allWrites count] > 0) { + FWriteRecord *lastRecord = self.allWrites[[self.allWrites count] - 1]; + self.lastWriteId = lastRecord.writeId; + } else { + self.lastWriteId = -1; + } +} + +/** + * The default filter used when constructing the tree. Keep everything that's + * visible. + */ ++ (BOOL (^)(FWriteRecord *record))defaultFilter { + static BOOL (^filter)(FWriteRecord *); + static dispatch_once_t filterToken; + dispatch_once(&filterToken, ^{ + filter = ^(FWriteRecord *record) { + return YES; + }; + }); + return filter; +} + +/** + * Static method. Given an array of WriteRecords, a filter for which ones to + * include, and a path, construct a merge at that path + * @return An FImmutableTree of ids. + */ ++ (FCompoundWrite *)layerTreeFromWrites:(NSArray *)writes + filter:(BOOL (^)(FWriteRecord *record))filter + treeRoot:(FPath *)treeRoot { + __block FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + // Theory, a later set will either: + // a) abort a relevant transaction, so no need to worry about excluding it + // from calculating that transaction b) not be relevant to a transaction + // (separate branch), so again will not affect the data for that + // transaction + if (filter(record)) { + FPath *writePath = record.path; + if ([record isOverwrite]) { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addWrite:record.overwrite + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + id child = [record.overwrite + getChild:[FPath relativePathFrom:writePath to:treeRoot]]; + compoundWrite = [compoundWrite addWrite:child + atPath:[FPath empty]]; + } else { + // There is no overlap between root path and write path, + // ignore write + } + } else { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addCompoundWrite:record.merge + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + FPath *relativePath = [FPath relativePathFrom:writePath + to:treeRoot]; + if (relativePath.isEmpty) { + compoundWrite = + [compoundWrite addCompoundWrite:record.merge + atPath:[FPath empty]]; + } else { + id child = + [record.merge completeNodeAtPath:relativePath]; + if (child != nil) { + // There exists a child in this node that matches the + // root path + id deepNode = + [child getChild:[relativePath popFront]]; + compoundWrite = + [compoundWrite addWrite:deepNode + atPath:[FPath empty]]; + } + } + } else { + // There is no overlap between root path and write path, + // ignore write + } + } + } + }]; + return compoundWrite; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h new file mode 100644 index 00000000..962ad5c0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FChildrenNode; +@class FPath; +@class FNamedNode; +@class FWriteRecord; +@class FWriteTree; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTreeRef : NSObject + +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree; + +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache; + +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (FChildrenNode *)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m new file mode 100644 index 00000000..809d1a98 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m @@ -0,0 +1,159 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTreeRef.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" + +@interface FWriteTreeRef () +/** + * The path to this particular FWriteTreeRef. Used for calling methods on + * writeTree while exposing a simpler interface to callers. + */ +@property(nonatomic, strong) FPath *path; +/** + * A reference to the actual tree of the write data. All methods are + * pass-through to the tree, but with the appropriate path prefixed. + * + * This lets us make cheap references to points in the tree for sync points + * without having to copy and maintain all of the data. + */ +@property(nonatomic, strong) FWriteTree *writeTree; +@end + +/** + * A FWriteTreeRef wraps a FWriteTree and a FPath, for convenient access to a + * particular subtree. All the methods just proxy to the underlying FWriteTree. + */ +@implementation FWriteTreeRef +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree { + self = [super init]; + if (self) { + self.path = aPath; + self.writeTree = tree; + } + return self; +} + +/** + * @return If possible, returns a complete event cache, using the underlying + * server data if possible. In addition, can be used to get a cache that + * includes hidden writes, and excludes arbitrary writes. Note that customizing + * the returned node can lead to a more expensive calculation. + */ +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache { + return [self.writeTree calculateCompleteEventCacheAtPath:self.path + completeServerCache:completeServerCache + excludeWriteIds:nil + includeHiddenWrites:NO]; +} + +/** + * @return If possible, returns a children node containing all of the complete + * children we have data for. The returned data is a mix of the given server + * data and write data. + */ +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (id)completeServerChildren { + return [self.writeTree + calculateCompleteEventChildrenAtPath:self.path + completeServerChildren:completeServerChildren]; +} + +/** + * Given that either the underlying server data has updated or the outstanding + * writes have been updating, determine what, if anything, needs to be applied + * to the event cache. + * + * Possibilities: + * + * 1. No writes are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some writes are completly shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events should be raised. + * + * Either existingEventSnap or existingServerSnap must exist, this is validated + * via an assert. + */ +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + return [self.writeTree + calculateEventCacheAfterServerOverwriteAtPath:self.path + childPath:childPath + existingEventSnap:existingEventSnap + existingServerSnap:existingServerSnap]; +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns nil if there + * is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.writeTree shadowingWriteAtPath:[self.path child:path]]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that are outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + return [self.writeTree calculateNextNodeAfterPost:post + atPath:self.path + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + return [self.writeTree calculateCompleteChildAtPath:self.path + childKey:childKey + cache:existingServerCache]; +} + +/** + * @return a WriteTreeref for a child. + */ +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey { + return + [[FWriteTreeRef alloc] initWithPath:[self.path childFromString:childKey] + writeTree:self.writeTree]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h new file mode 100644 index 00000000..97a23bfc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FPath; +@class FOperationSource; +@class FImmutableTree; + +@interface FAckUserWrite : NSObject + +- initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)affectedTree + revert:(BOOL)shouldRevert; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +// A FImmutableTree, containing @YES for each affected path. Affected paths +// can't overlap. +@property(nonatomic, strong, readonly) FImmutableTree *affectedTree; +@property(nonatomic, readonly) BOOL revert; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m new file mode 100644 index 00000000..2a1f2874 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAckUserWrite.h" +#import "FImmutableTree.h" +#import "FOperationSource.h" +#import "FPath.h" + +@implementation FAckUserWrite + +- (id)initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)tree + revert:(BOOL)shouldRevert { + self = [super init]; + if (self) { + self->_source = [FOperationSource userInstance]; + self->_type = FOperationTypeAckUserWrite; + self->_path = operationPath; + self->_affectedTree = tree; + self->_revert = shouldRevert; + } + return self; +} + +- (FAckUserWrite *)operationForChild:(NSString *)childKey { + if (![self.path isEmpty]) { + NSAssert([self.path.getFront isEqualToString:childKey], + @"operationForChild called for unrelated child."); + return [[FAckUserWrite alloc] initWithPath:[self.path popFront] + affectedTree:self.affectedTree + revert:self.revert]; + } else if (self.affectedTree.value != nil) { + NSAssert(self.affectedTree.children.isEmpty, + @"affectedTree should not have overlapping affected paths."); + // All child locations are affected as well; just return same operation. + return self; + } else { + FImmutableTree *childTree = + [self.affectedTree subtreeAtPath:[[FPath alloc] initWith:childKey]]; + return [[FAckUserWrite alloc] initWithPath:[FPath empty] + affectedTree:childTree + revert:self.revert]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat: + @"FAckUserWrite { path=%@, revert=%d, affectedTree=%@ }", + self.path, self.revert, self.affectedTree]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h new file mode 100644 index 00000000..56fbec9f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FCompoundWrite; + +@interface FMerge : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)children; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FCompoundWrite *children; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m new file mode 100644 index 00000000..c3447554 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m @@ -0,0 +1,85 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMerge.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" + +@interface FMerge () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) FCompoundWrite *children; +@end + +@implementation FMerge + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize children; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)someChildren { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeMerge; + self.path = aPath; + self.children = someChildren; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + FCompoundWrite *childTree = [self.children + childCompoundWriteAtPath:[[FPath alloc] initWith:childKey]]; + if (childTree.isEmpty) { + return nil; + } else if (childTree.rootWrite != nil) { + // We have a snapshot for the child in question. This becomes an + // overwrite of the child. + return [[FOverwrite alloc] initWithSource:self.source + path:[FPath empty] + snap:childTree.rootWrite]; + } else { + // This is a merge at a deeper level + return [[FMerge alloc] initWithSource:self.source + path:[FPath empty] + children:childTree]; + } + } else { + NSAssert( + [self.path.getFront isEqualToString:childKey], + @"Can't get a merge for a child not on the path of the operation"); + return [[FMerge alloc] initWithSource:self.source + path:[self.path popFront] + children:self.children]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"FMerge { path=%@, soruce=%@ children=%@}", + self.path, self.source, self.children]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h new file mode 100644 index 00000000..41f60549 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FOperationSource; +@class FPath; + +typedef NS_ENUM(NSInteger, FOperationType) { + FOperationTypeOverwrite = 0, + FOperationTypeMerge = 1, + FOperationTypeAckUserWrite = 2, + FOperationTypeListenComplete = 3 +}; + +@protocol FOperation +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +- (id)operationForChild:(NSString *)childKey; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h new file mode 100644 index 00000000..747487b5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQueryParams; + +@interface FOperationSource : NSObject + +@property(nonatomic, readonly) BOOL fromUser; +@property(nonatomic, readonly) BOOL fromServer; +@property(nonatomic, readonly) BOOL isTagged; +@property(nonatomic, strong, readonly) FQueryParams *queryParams; + +- initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)isTagged; + ++ (FOperationSource *)userInstance; ++ (FOperationSource *)serverInstance; ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m new file mode 100644 index 00000000..92e3db8c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FOperationSource () +@property(nonatomic, readwrite) BOOL fromUser; +@property(nonatomic, readwrite) BOOL fromServer; +@property(nonatomic, readwrite) BOOL isTagged; +@property(nonatomic, strong, readwrite) FQueryParams *queryParams; +@end + +@implementation FOperationSource + +@synthesize fromUser; +@synthesize fromServer; +@synthesize queryParams; + +- (id)initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)tagged { + self = [super init]; + if (self) { + self.fromUser = isFromUser; + self.fromServer = isFromServer; + self.queryParams = params; + self.isTagged = tagged; + } + return self; +} + ++ (FOperationSource *)userInstance { + static FOperationSource *user = nil; + static dispatch_once_t userToken; + dispatch_once(&userToken, ^{ + user = [[FOperationSource alloc] initWithFromUser:YES + fromServer:NO + queryParams:nil + tagged:NO]; + }); + return user; +} + ++ (FOperationSource *)serverInstance { + static FOperationSource *server = nil; + static dispatch_once_t serverToken; + dispatch_once(&serverToken, ^{ + server = [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:nil + tagged:NO]; + }); + return server; +} + ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params { + return [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:params + tagged:YES]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FOperationSource { fromUser=%d, " + @"fromServer=%d, queryId=%@, tagged=%d }", + self.fromUser, self.fromServer, + self.queryParams, self.isTagged]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h new file mode 100644 index 00000000..7d738ac4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@protocol FNode; + +@interface FOverwrite : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id snap; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m new file mode 100644 index 00000000..ad4daec9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOverwrite.h" +#import "FNode.h" +#import "FOperationSource.h" + +@interface FOverwrite () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) id snap; +@end + +@implementation FOverwrite + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize snap; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeOverwrite; + self.path = aPath; + self.snap = aSnap; + } + return self; +} + +- (FOverwrite *)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FOverwrite alloc] + initWithSource:self.source + path:[FPath empty] + snap:[self.snap getImmediateChild:childKey]]; + } else { + return [[FOverwrite alloc] initWithSource:self.source + path:[self.path popFront] + snap:self.snap]; + } +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"FOverwrite { path=%@, source=%@, snapshot=%@ }", + self.path, self.source, self.snap]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h new file mode 100644 index 00000000..a63d0d83 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRRetryHelper : NSObject + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor; + +- (void)retry:(void (^)(void))block; + +- (void)cancel; + +- (void)signalSuccess; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m new file mode 100644 index 00000000..f94c5ede --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRRetryHelper.h" +#import "FUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FIRRetryHelperTask : NSObject + +@property(nonatomic, strong) void (^block)(void); + +@end + +@implementation FIRRetryHelperTask + +- (instancetype)initWithBlock:(void (^)(void))block { + self = [super init]; + if (self != nil) { + self->_block = [block copy]; + } + return self; +} + +- (BOOL)isCanceled { + return self.block == nil; +} + +- (void)cancel { + self.block = nil; +} + +- (void)execute { + if (self.block) { + self.block(); + } +} + +@end + +@interface FIRRetryHelper () + +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic) NSTimeInterval minRetryDelayAfterFailure; +@property(nonatomic) NSTimeInterval maxRetryDelay; +@property(nonatomic) double retryExponent; +@property(nonatomic) double jitterFactor; + +@property(nonatomic) BOOL lastWasSuccess; +@property(nonatomic) NSTimeInterval currentRetryDelay; + +@property(nonatomic, strong) FIRRetryHelperTask *scheduledRetry; + +@end + +@implementation FIRRetryHelper + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor { + self = [super init]; + if (self != nil) { + self->_dispatchQueue = dispatchQueue; + self->_minRetryDelayAfterFailure = minRetryDelayAfterFailure; + self->_maxRetryDelay = maxRetryDelay; + self->_retryExponent = retryExponent; + self->_jitterFactor = jitterFactor; + self->_lastWasSuccess = YES; + } + return self; +} + +- (void)retry:(void (^)(void))block { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054001", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } + + NSTimeInterval delay; + if (self.lastWasSuccess) { + delay = 0; + } else { + if (self.currentRetryDelay == 0) { + self.currentRetryDelay = self.minRetryDelayAfterFailure; + } else { + NSTimeInterval newDelay = + (self.currentRetryDelay * self.retryExponent); + self.currentRetryDelay = MIN(newDelay, self.maxRetryDelay); + } + + delay = ((1 - self.jitterFactor) * self.currentRetryDelay) + + (self.jitterFactor * self.currentRetryDelay * + [FUtilities randomDouble]); + FFLog(@"I-RDB054002", @"Scheduling retry in %fs", delay); + } + self.lastWasSuccess = NO; + FIRRetryHelperTask *task = [[FIRRetryHelperTask alloc] initWithBlock:block]; + self.scheduledRetry = task; + dispatch_time_t popTime = + dispatch_time(DISPATCH_TIME_NOW, (long long)(delay * NSEC_PER_SEC)); + dispatch_after(popTime, self.dispatchQueue, ^{ + if (![task isCanceled]) { + self.scheduledRetry = nil; + [task execute]; + } + }); +} + +- (void)signalSuccess { + self.lastWasSuccess = YES; + self.currentRetryDelay = 0; +} + +- (void)cancel { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054003", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } else { + FFLog(@"I-RDB054004", @"No existing retry attempt to cancel"); + } + self.currentRetryDelay = 0; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h new file mode 100644 index 00000000..e6d49618 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FTuplePathValue.h" + +@interface FImmutableTree : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap; + ++ (FImmutableTree *)empty; +- (BOOL)isEmpty; + +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id))predicate; +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath; +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath; +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath; +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath; +- (id)valueAtPath:(FPath *)relativePath; +- (id)rootMostValueOnPath:(FPath *)path; +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate; +- (id)leafMostValueOnPath:(FPath *)path; +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate; +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate; +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath; +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block; +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block; +- (FPath *)forEachOnPath:(FPath *)path + whileBlock:(BOOL (^)(FPath *path, id value))block; +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block; +- (void)forEach:(void (^)(FPath *path, id value))block; +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block; + +@property(nonatomic, strong, readonly) id value; +@property(nonatomic, strong, readonly) FImmutableSortedDictionary *children; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m new file mode 100644 index 00000000..34e62ae6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m @@ -0,0 +1,486 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableTree.h" +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FUtilities.h" + +@interface FImmutableTree () +@property(nonatomic, strong, readwrite) id value; +/** + * Maps NSString -> FImmutableTree, where is type of value. + */ +@property(nonatomic, strong, readwrite) FImmutableSortedDictionary *children; +@end + +@implementation FImmutableTree +@synthesize value; +@synthesize children; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.children = [FImmutableTree emptyChildren]; + } + return self; +} + +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap { + self = [super init]; + if (self) { + self.value = aValue; + self.children = childrenMap; + } + return self; +} + ++ (FImmutableSortedDictionary *)emptyChildren { + static dispatch_once_t emptyChildrenToken; + static FImmutableSortedDictionary *emptyChildren; + dispatch_once(&emptyChildrenToken, ^{ + emptyChildren = [FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities stringComparator]]; + }); + return emptyChildren; +} + ++ (FImmutableTree *)empty { + static dispatch_once_t emptyImmutableTreeToken; + static FImmutableTree *emptyTree = nil; + dispatch_once(&emptyImmutableTreeToken, ^{ + emptyTree = [[FImmutableTree alloc] initWithValue:nil]; + }); + return emptyTree; +} + +- (BOOL)isEmpty { + return self.value == nil && [self.children isEmpty]; +} + +/** + * Given a path and a predicate, return the first node and the path to that node + * where the predicate returns true + * // TODO Do a perf test. If we're creating a bunch of FTuplePathValue objects + * on the way back out, it may be better to pass down a pathSoFar FPath + */ +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id value))predicate { + if (self.value != nil && predicate(self.value)) { + return [[FTuplePathValue alloc] initWithPath:[FPath empty] + value:self.value]; + } else { + if ([relativePath isEmpty]) { + return nil; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child != nil) { + FTuplePathValue *childExistingPathAndValue = + [child findRootMostMatchingPath:[relativePath popFront] + predicate:predicate]; + if (childExistingPathAndValue != nil) { + FPath *fullPath = [[[FPath alloc] initWith:front] + child:childExistingPathAndValue.path]; + return [[FTuplePathValue alloc] + initWithPath:fullPath + value:childExistingPathAndValue.value]; + } else { + return nil; + } + } else { + // No child matching path + return nil; + } + } + } +} + +/** + * Find, if it exists, the shortest subpath of the given path that points a + * defined value in the tree + */ +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath { + return [self findRootMostMatchingPath:relativePath + predicate:^BOOL(__unsafe_unretained id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path { + return [self rootMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return self.value; + } else if (path.isEmpty) { + return nil; + } else { + return [[self.children get:path.getFront] + rootMostValueOnPath:[path popFront] + matching:predicate]; + } +} + +- (id)leafMostValueOnPath:(FPath *)path { + return [self leafMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate { + __block id currentValue = self.value; + __block FImmutableTree *currentTree = self; + [relativePath enumerateComponentsUsingBlock:^(NSString *key, BOOL *stop) { + currentTree = [currentTree.children get:key]; + if (currentTree == nil) { + *stop = YES; + } else { + id treeValue = currentTree.value; + if (treeValue != nil && predicate(treeValue)) { + currentValue = treeValue; + } + } + }]; + return currentValue; +} + +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return YES; + } else { + __block BOOL found = NO; + [self.children enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *subtree, BOOL *stop) { + found = [subtree containsValueMatching:predicate]; + if (found) + *stop = YES; + }]; + return found; + } +} + +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *childTree = [self.children get:front]; + if (childTree != nil) { + return [childTree subtreeAtPath:[relativePath popFront]]; + } else { + return [FImmutableTree empty]; + } + } +} + +/** + * Sets a value at the specified path + */ +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return [[FImmutableTree alloc] initWithValue:newValue + children:self.children]; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setValue:newValue + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren = + [self.children insertKey:front withValue:newChild]; + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Remove the value at the specified path + */ +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + if ([self.children isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:nil + children:self.children]; + } + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + FImmutableTree *newChild = + [child removeValueAtPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front + withValue:newChild]; + } + if (self.value == nil && [newChildren isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } + } else { + return self; + } + } +} + +/** + * Gets a value from the tree + */ +- (id)valueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self.value; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + return [child valueAtPath:[relativePath popFront]]; + } else { + return nil; + } + } +} + +/** + * Replaces the subtree at the specified path with the given new tree + */ +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return newTree; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setTree:newTree + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front withValue:newChild]; + } + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Performs a depth first fold on this tree. Transforms a tree into a single + * value, given a function that operates on the path to a node, an optional + * current value, and a map of the child names to folded subtrees + */ +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + return [self foldWithPathSoFar:[FPath empty] withBlock:block]; +} + +/** + * Recursive helper for public facing foldWithBlock: method + */ +- (id)foldWithPathSoFar:(FPath *)pathSoFar + withBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + __block NSMutableDictionary *accum = [[NSMutableDictionary alloc] init]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + accum[childKey] = + [childTree foldWithPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + return block(pathSoFar, self.value, accum); +} + +/** + * Find the first matching value on the given path. Return the result of + * applying block to it. + */ +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block { + return [self findOnPath:path pathSoFar:[FPath empty] andApplyBlock:block]; +} + +- (id)findOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + andApplyBlock:(id (^)(FPath *path, id value))block { + id result = self.value ? block(pathSoFar, self.value) : nil; + if (result != nil) { + return result; + } else { + if ([pathToFollow isEmpty]) { + return nil; + } else { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild != nil) { + return [nextChild findOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + andApplyBlock:block]; + } else { + return nil; + } + } + } +} +/** + * Call the block on each value along the path for as long as that function + * returns true + * @return The path to the deepest location inspected + */ +- (FPath *)forEachOnPath:(FPath *)path whileBlock:(BOOL (^)(FPath *, id))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] whileBlock:block]; +} + +- (FPath *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + whileBlock:(BOOL (^)(FPath *, id))block { + if ([pathToFollow isEmpty]) { + if (self.value) { + block(pathSoFar, self.value); + } + return pathSoFar; + } else { + BOOL shouldContinue = YES; + if (self.value) { + shouldContinue = block(pathSoFar, self.value); + } + if (shouldContinue) { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return + [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + whileBlock:block]; + } else { + return pathSoFar; + } + } else { + return pathSoFar; + } + } +} + +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] performBlock:block]; +} + +- (FImmutableTree *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + performBlock:(void (^)(FPath *path, id value))block { + if ([pathToFollow isEmpty]) { + return self; + } else { + if (self.value) { + block(pathSoFar, self.value); + } + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + performBlock:block]; + } else { + return [FImmutableTree empty]; + } + } +} +/** + * Calls the given block for each node in the tree that has a value. Called in + * depth-first order + */ +- (void)forEach:(void (^)(FPath *path, id value))block { + [self forEachPathSoFar:[FPath empty] withBlock:block]; +} + +- (void)forEachPathSoFar:(FPath *)pathSoFar + withBlock:(void (^)(FPath *path, id value))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [childTree forEachPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + if (self.value) { + block(pathSoFar, self.value); + } +} + +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value) { + block(childKey, childTree.value); + } + }]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableTree class]]) { + return NO; + } + FImmutableTree *other = (FImmutableTree *)object; + return (self.value == other.value || [self.value isEqual:other.value]) && + [self.children isEqual:other.children]; +} + +- (NSUInteger)hash { + return self.children.hash * 31 + [self.value hash]; +} + +- (NSString *)description { + NSMutableString *string = [[NSMutableString alloc] init]; + [string appendString:@"FImmutableTree { value="]; + [string appendString:(self.value ? [self.value description] : @"")]; + [string appendString:@", children={"]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [string appendString:@" "]; + [string appendString:childKey]; + [string appendString:@"="]; + [string appendString:[childTree.value description]]; + }]; + [string appendString:@" } }"]; + return [NSString stringWithString:string]; +} + +- (NSString *)debugDescription { + return [self description]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h new file mode 100644 index 00000000..cfa86aac --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FPath : NSObject + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner; ++ (FPath *)empty; ++ (FPath *)pathWithString:(NSString *)string; + +- (id)initWith:(NSString *)path; +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum; + +- (id)copyWithZone:(NSZone *)zone; + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *key, + BOOL *stop))block; +- (NSString *)getFront; +- (NSUInteger)length; +- (FPath *)popFront; +- (NSString *)getBack; +- (NSString *)toString; +- (NSString *)toStringWithTrailingSlash; +- (NSString *)wireFormat; +- (FPath *)parent; +- (FPath *)child:(FPath *)childPathObj; +- (FPath *)childFromString:(NSString *)childPath; +- (BOOL)isEmpty; +- (BOOL)contains:(FPath *)other; +- (NSComparisonResult)compare:(FPath *)other; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m new file mode 100644 index 00000000..f6552400 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" + +#import "FUtilities.h" + +@interface FPath () + +@property(nonatomic, readwrite, assign) NSInteger pieceNum; +@property(nonatomic, strong) NSArray *pieces; + +@end + +@implementation FPath + +#pragma mark - +#pragma mark Initializers + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner { + NSString *outerFront = [outer getFront]; + NSString *innerFront = [inner getFront]; + if (outerFront == nil) { + return inner; + } else if ([outerFront isEqualToString:innerFront]) { + return [self relativePathFrom:[outer popFront] to:[inner popFront]]; + } else { + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:[NSString + stringWithFormat: + @"innerPath (%@) is not within outerPath (%@)", + inner, outer] + userInfo:nil]; + } +} + ++ (FPath *)pathWithString:(NSString *)string { + return [[FPath alloc] initWith:string]; +} + +- (id)initWith:(NSString *)path { + self = [super init]; + if (self) { + NSArray *pathPieces = [path componentsSeparatedByString:@"/"]; + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + self.pieces = newPieces; + self.pieceNum = 0; + } + return self; +} + +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum { + self = [super init]; + if (self) { + self.pieceNum = aPieceNum; + self.pieces = somePieces; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable, so it's safe to return self + return self; +} + +- (NSString *)description { + return [self toString]; +} + +#pragma mark - +#pragma mark Public methods + +- (NSString *)getFront { + if (self.pieceNum >= self.pieces.count) { + return nil; + } + return [self.pieces objectAtIndex:self.pieceNum]; +} + +/** + * @return The number of segments in this path + */ +- (NSUInteger)length { + return self.pieces.count - self.pieceNum; +} + +- (FPath *)popFront { + NSInteger newPieceNum = self.pieceNum; + if (newPieceNum < self.pieces.count) { + newPieceNum++; + } + return [[FPath alloc] initWithPieces:self.pieces andPieceNum:newPieceNum]; +} + +- (NSString *)getBack { + if (self.pieceNum < self.pieces.count) { + return [self.pieces lastObject]; + } else { + return nil; + } +} + +- (NSString *)toString { + return [self toStringWithTrailingSlash:NO]; +} + +- (NSString *)toStringWithTrailingSlash { + return [self toStringWithTrailingSlash:YES]; +} + +- (NSString *)toStringWithTrailingSlash:(BOOL)trailingSlash { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [pathString appendString:@"/"]; + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + if ([pathString length] == 0) { + return @"/"; + } else { + if (trailingSlash) { + [pathString appendString:@"/"]; + } + return pathString; + } +} + +- (NSString *)wireFormat { + if ([self isEmpty]) { + return @"/"; + } else { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + if (i > self.pieceNum) { + [pathString appendString:@"/"]; + } + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + return pathString; + } +} + +- (FPath *)parent { + if (self.pieceNum >= self.pieces.count) { + return nil; + } else { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count - 1; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; + } +} + +- (FPath *)child:(FPath *)childPathObj { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + for (NSInteger i = childPathObj.pieceNum; i < childPathObj.pieces.count; + i++) { + [newPieces addObject:[childPathObj.pieces objectAtIndex:i]]; + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +- (FPath *)childFromString:(NSString *)childPath { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + NSArray *pathPieces = [childPath componentsSeparatedByString:@"/"]; + for (unsigned int i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +/** + * @return True if there are no segments in this path + */ +- (BOOL)isEmpty { + return self.pieceNum >= self.pieces.count; +} + +/** + * @return Singleton to represent an empty path + */ ++ (FPath *)empty { + static dispatch_once_t oneEmptyPath; + static FPath *emptyPath; + dispatch_once(&oneEmptyPath, ^{ + emptyPath = [[FPath alloc] initWith:@""]; + }); + return emptyPath; +} + +- (BOOL)contains:(FPath *)other { + if (self.length > other.length) { + return NO; + } + + NSInteger i = self.pieceNum; + NSInteger j = other.pieceNum; + while (i < self.pieces.count) { + NSString *thisSeg = [self.pieces objectAtIndex:i]; + NSString *otherSeg = [other.pieces objectAtIndex:j]; + if (![thisSeg isEqualToString:otherSeg]) { + return NO; + } + ++i; + ++j; + } + return YES; +} + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *, BOOL *))block { + BOOL stop = NO; + for (NSInteger i = self.pieceNum; !stop && i < self.pieces.count; i++) { + block(self.pieces[i], &stop); + } +} + +- (NSComparisonResult)compare:(FPath *)other { + NSInteger myCount = self.pieces.count; + NSInteger otherCount = other.pieces.count; + for (NSInteger i = self.pieceNum, j = other.pieceNum; + i < myCount && j < otherCount; i++, j++) { + NSComparisonResult comparison = [FUtilities compareKey:self.pieces[i] + toKey:other.pieces[j]]; + if (comparison != NSOrderedSame) { + return comparison; + } + } + if (self.length < other.length) { + return NSOrderedAscending; + } else if (other.length < self.length) { + return NSOrderedDescending; + } else { + NSAssert(self.length == other.length, + @"Paths must be the same lengths"); + return NSOrderedSame; + } +} + +/** + * @return YES if paths are the same + */ +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (!other || ![other isKindOfClass:[self class]]) { + return NO; + } + FPath *otherPath = (FPath *)other; + if (self.length != otherPath.length) { + return NO; + } + for (NSUInteger i = self.pieceNum, j = otherPath.pieceNum; + i < self.pieces.count; i++, j++) { + if (![self.pieces[i] isEqualToString:otherPath.pieces[j]]) { + return NO; + } + } + return YES; +} + +- (NSUInteger)hash { + NSUInteger hashCode = 0; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + hashCode = hashCode * 37 + [self.pieces[i] hash]; + } + return hashCode; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h new file mode 100644 index 00000000..d5c77ab0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTreeNode.h" +#import + +@interface FTree : NSObject + +- (id)init; +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode; + +- (FTree *)subTree:(FPath *)path; +- (id)getValue; +- (void)setValue:(id)value; +- (void)clear; +- (BOOL)hasChildren; +- (BOOL)isEmpty; +- (void)forEachChildMutationSafe:(void (^)(FTree *))action; +- (void)forEachChild:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf; +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action; +- (BOOL)valueExistsAtOrAbove:(FPath *)path; +- (FPath *)path; +- (void)updateParents; +- (void)updateChild:(NSString *)childName withNode:(FTree *)child; + +@property(nonatomic, strong) NSString *name; +@property(nonatomic, strong) FTree *parent; +@property(nonatomic, strong) FTreeNode *node; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m new file mode 100644 index 00000000..209b59f9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m @@ -0,0 +1,193 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTree.h" +#import "FPath.h" +#import "FTreeNode.h" +#import "FUtilities.h" + +@implementation FTree + +@synthesize name; +@synthesize parent; +@synthesize node; + +- (id)init { + self = [super init]; + if (self) { + self.name = @""; + self.parent = nil; + self.node = [[FTreeNode alloc] init]; + } + return self; +} + +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode { + self = [super init]; + if (self) { + self.name = aName != nil ? aName : @""; + self.parent = aParent != nil ? aParent : nil; + self.node = aNode != nil ? aNode : [[FTreeNode alloc] init]; + } + return self; +} + +- (FTree *)subTree:(FPath *)path { + FTree *child = self; + NSString *next = [path getFront]; + while (next != nil) { + FTreeNode *childNode = child.node.children[next]; + if (childNode == nil) { + childNode = [[FTreeNode alloc] init]; + } + child = [[FTree alloc] initWithName:next + withParent:child + withNode:childNode]; + path = [path popFront]; + next = [path getFront]; + } + return child; +} + +- (id)getValue { + return self.node.value; +} + +- (void)setValue:(id)value { + self.node.value = value; + [self updateParents]; +} + +- (void)clear { + self.node.value = nil; + [self.node.children removeAllObjects]; + self.node.childCount = 0; + [self updateParents]; +} + +- (BOOL)hasChildren { + return self.node.childCount > 0; +} + +- (BOOL)isEmpty { + return [self getValue] == nil && ![self hasChildren]; +} + +- (void)forEachChild:(void (^)(FTree *))action { + for (NSString *key in self.node.children) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachChildMutationSafe:(void (^)(FTree *))action { + for (NSString *key in [self.node.children copy]) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachDescendant:(void (^)(FTree *))action { + [self forEachDescendant:action includeSelf:NO childrenFirst:NO]; +} + +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst { + if (incSelf && !childFirst) { + action(self); + } + + [self forEachChild:^(FTree *child) { + [child forEachDescendant:action includeSelf:YES childrenFirst:childFirst]; + }]; + + if (incSelf && childFirst) { + action(self); + } +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action { + return [self forEachAncestor:action includeSelf:NO]; +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf { + FTree *aNode = (incSelf) ? self : self.parent; + while (aNode != nil) { + if (action(aNode)) { + return YES; + } + aNode = aNode.parent; + } + return NO; +} + +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action { + [self forEachChild:^(FTree *child) { + if ([child getValue] != nil) { + action(child); + } else { + [child forEachImmediateDescendantWithValue:action]; + } + }]; +} + +- (BOOL)valueExistsAtOrAbove:(FPath *)path { + FTreeNode *aNode = self.node; + while (aNode != nil) { + if (aNode.value != nil) { + return YES; + } + aNode = [aNode.children objectForKey:path.getFront]; + path = [path popFront]; + } + // XXX Check with Michael if this is correct; deviates from JS. + return NO; +} + +- (FPath *)path { + return [[FPath alloc] + initWith:(self.parent == nil) + ? self.name + : [NSString stringWithFormat:@"%@/%@", [self.parent path], + self.name]]; +} + +- (void)updateParents { + [self.parent updateChild:self.name withNode:self]; +} + +- (void)updateChild:(NSString *)childName withNode:(FTree *)child { + BOOL childEmpty = [child isEmpty]; + BOOL childExists = self.node.children[childName] != nil; + if (childEmpty && childExists) { + [self.node.children removeObjectForKey:childName]; + self.node.childCount = self.node.childCount - 1; + [self updateParents]; + } else if (!childEmpty && !childExists) { + [self.node.children setObject:child.node forKey:childName]; + self.node.childCount = self.node.childCount + 1; + [self updateParents]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h new file mode 100644 index 00000000..549f3b1e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTreeNode : NSObject + +@property(nonatomic, strong) NSMutableDictionary *children; +@property(nonatomic, readwrite, assign) int childCount; +@property(nonatomic, strong) id value; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m new file mode 100644 index 00000000..bae6c627 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTreeNode.h" + +@implementation FTreeNode + +@synthesize children; +@synthesize childCount; +@synthesize value; + +- (id)init { + self = [super init]; + if (self) { + self.children = [[NSMutableDictionary alloc] init]; + self.childCount = 0; + self.value = nil; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h new file mode 100644 index 00000000..eff0cb0b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@class FPath; + +/** + * A cache node only stores complete children. Additionally it holds a flag + * whether the node can be considered fully initialized in the sense that we + * know at one point in time, this represented a valid state of the world, e.g. + * initialized with data from the server, or a complete overwrite by the client. + * It is not necessarily complete because it may have been from a tagged query. + * The filtered flag also tracks whether a node potentially had children removed + * due to a filter. + */ +@interface FCacheNode : NSObject + +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered; + +- (BOOL)isCompleteForPath:(FPath *)path; +- (BOOL)isCompleteForChild:(NSString *)childKey; + +@property(nonatomic, readonly) BOOL isFullyInitialized; +@property(nonatomic, readonly) BOOL isFiltered; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) id node; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m new file mode 100644 index 00000000..a991d52e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FPath.h" + +@interface FCacheNode () +@property(nonatomic, readwrite) BOOL isFullyInitialized; +@property(nonatomic, readwrite) BOOL isFiltered; +@property(nonatomic, strong, readwrite) FIndexedNode *indexedNode; +@end + +@implementation FCacheNode +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered { + self = [super init]; + if (self) { + self.indexedNode = indexedNode; + self.isFullyInitialized = fullyInitialized; + self.isFiltered = filtered; + } + return self; +} + +- (BOOL)isCompleteForPath:(FPath *)path { + if (path.isEmpty) { + return self.isFullyInitialized && !self.isFiltered; + } else { + NSString *childKey = [path getFront]; + return [self isCompleteForChild:childKey]; + } +} + +- (BOOL)isCompleteForChild:(NSString *)childKey { + return (self.isFullyInitialized && !self.isFiltered) || + [self.node hasChild:childKey]; +} + +- (id)node { + return self.indexedNode.node; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h new file mode 100644 index 00000000..dd586427 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import + +@protocol FEventRegistration; + +@interface FCancelEvent : NSObject + +- initWithEventRegistration:(id)eventRegistration + error:(NSError *)error + path:(FPath *)path; + +@property(nonatomic, strong, readonly) NSError *error; +@property(nonatomic, strong, readonly) FPath *path; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m new file mode 100644 index 00000000..b069a71e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCancelEvent.h" +#import "FEventRegistration.h" +#import "FPath.h" + +@interface FCancelEvent () +@property(nonatomic, strong) id eventRegistration; +@property(nonatomic, strong, readwrite) NSError *error; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FCancelEvent + +@synthesize eventRegistration; +@synthesize error; +@synthesize path; + +- (id)initWithEventRegistration:(id)registration + error:(NSError *)anError + path:(FPath *)aPath { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.error = anError; + self.path = aPath; + } + return self; +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return YES; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@: cancel", self.path]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h new file mode 100644 index 00000000..101ec8f4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import + +@interface FChange : NSObject + +@property(nonatomic, readonly) FIRDataEventType type; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) NSString *childKey; +@property(nonatomic, strong, readonly) NSString *prevKey; +@property(nonatomic, strong, readonly) FIndexedNode *oldIndexedNode; + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode; + +- (FChange *)changeWithPrevKey:(NSString *)prevKey; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m new file mode 100644 index 00000000..8ad1cfce --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" + +@interface FChange () + +@property(nonatomic, strong, readwrite) NSString *prevKey; + +@end + +@implementation FChange + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode { + return [self initWithType:type + indexedNode:indexedNode + childKey:nil + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey { + return [self initWithType:type + indexedNode:indexedNode + childKey:childKey + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode { + self = [super init]; + if (self != nil) { + self->_type = type; + self->_indexedNode = indexedNode; + self->_childKey = childKey; + self->_oldIndexedNode = oldIndexedNode; + } + return self; +} + +- (FChange *)changeWithPrevKey:(NSString *)prevKey { + FChange *newChange = [[FChange alloc] initWithType:self.type + indexedNode:self.indexedNode + childKey:self.childKey + oldIndexedNode:self.oldIndexedNode]; + newChange.prevKey = prevKey; + return newChange; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event: %d, data: %@", (int)self.type, + [self.indexedNode.node val]]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h new file mode 100644 index 00000000..0b0c6335 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FChildEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +/** + * Maps FIRDataEventType (as NSNumber) to fbt_void_datasnapshot_nsstring + */ +@property(nonatomic, copy, readonly) NSDictionary *callbacks; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m new file mode 100644 index 00000000..fe1fa15b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FChildEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) NSDictionary *callbacks; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FChildEventRegistration + +- (id)initWithRepo:(id)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callbacks = callbackBlocks; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return self.callbacks != nil && + [self.callbacks + objectForKey:[NSNumber numberWithInteger:eventType]] != nil; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[query.path childFromString:change.childKey]]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:change.type + eventRegistration:self + dataSnapshot:snapshot + prevName:change.prevKey]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB061001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callbacks != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB061002", @"Raising event callback (%ld) on %@", + (long)dataEvent.eventType, dataEvent.path); + fbt_void_datasnapshot_nsstring callback = [self.callbacks + objectForKey:[NSNumber numberWithInteger:dataEvent.eventType]]; + + if (callback != nil) { + dispatch_async(queue, ^{ + callback(dataEvent.snapshot, dataEvent.prevName); + }); + } + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h new file mode 100644 index 00000000..a0d28f94 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabaseReference.h" +#import "FTupleUserCallback.h" +#import + +@protocol FEventRegistration; +@protocol FIndex; + +@interface FDataEvent : NSObject + +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot; +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)snapshot + prevName:(NSString *)prevName; + +@property(nonatomic, strong, readonly) id eventRegistration; +@property(nonatomic, strong, readonly) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readonly) NSString *prevName; +@property(nonatomic, readonly) FIRDataEventType eventType; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m new file mode 100644 index 00000000..886a21e3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FDataEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndex.h" + +@interface FDataEvent () +@property(nonatomic, strong, readwrite) id + eventRegistration; +@property(nonatomic, strong, readwrite) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readwrite) NSString *prevName; +@property(nonatomic, readwrite) FIRDataEventType eventType; +@end + +@implementation FDataEvent + +@synthesize eventRegistration; +@synthesize snapshot; +@synthesize prevName; +@synthesize eventType; + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot { + return [self initWithEventType:type + eventRegistration:registration + dataSnapshot:dataSnapshot + prevName:nil]; +} + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot + prevName:(NSString *)previousName { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.snapshot = dataSnapshot; + self.prevName = previousName; + self.eventType = type; + } + return self; +} + +- (FPath *)path { + // Used for logging, so delay calculation + FIRDatabaseReference *ref = self.snapshot.ref; + if (self.eventType == FIRDataEventTypeValue) { + return ref.path; + } else { + return ref.parent.path; + } +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return NO; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event %d, data: %@", (int)eventType, + [snapshot value]]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h new file mode 100644 index 00000000..cddcf735 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import + +@class FPath; + +@protocol FEvent +- (FPath *)path; +- (void)fireEventOnQueue:(dispatch_queue_t)queue; +- (BOOL)isCancelEvent; +- (NSString *)description; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h new file mode 100644 index 00000000..c46bff54 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" + +@class FPath; +@class FRepo; +@class FIRDatabaseConfig; + +/** + * Left as instance methods rather than class methods so that we could + * potentially callback on different queues for different repos. This is + * semi-parallel to JS's FEventQueue + */ +@interface FEventRaiser : NSObject + +- (id)initWithQueue:(dispatch_queue_t)queue; + +- (void)raiseEvents:(NSArray *)eventDataList; +- (void)raiseCallback:(fbt_void_void)callback; +- (void)raiseCallbacks:(NSArray *)callbackList; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m new file mode 100644 index 00000000..d745358c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRaiser.h" +#import "FDataEvent.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTupleUserCallback.h" +#import "FTypedefs.h" +#import "FUtilities.h" + +@interface FEventRaiser () + +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +/** + * This class exists for symmetry with other clients, but since events are + * async, we don't need to do the complicated stuff the JS client does to + * preserve event order. + */ +@implementation FEventRaiser + +- (id)init { + [NSException raise:NSInternalInconsistencyException + format:@"Can't use default constructor"]; + return nil; +} + +- (id)initWithQueue:(dispatch_queue_t)queue { + self = [super init]; + if (self != nil) { + self->_queue = queue; + } + return self; +} + +- (void)raiseEvents:(NSArray *)eventDataList { + for (id event in eventDataList) { + [event fireEventOnQueue:self.queue]; + } +} + +- (void)raiseCallback:(fbt_void_void)callback { + dispatch_async(self.queue, callback); +} + +- (void)raiseCallbacks:(NSArray *)callbackList { + for (fbt_void_void callback in callbackList) { + dispatch_async(self.queue, callback); + } +} + ++ (void)raiseCallbacks:(NSArray *)callbackList queue:(dispatch_queue_t)queue { + for (fbt_void_void callback in callbackList) { + dispatch_async(queue, callback); + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h new file mode 100644 index 00000000..79a2eb08 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" +#import "FIRDataEventType.h" +#import + +@protocol FEvent; +@class FDataEvent; +@class FCancelEvent; +@class FQuerySpec; + +@protocol FEventRegistration +- (BOOL)responseTo:(FIRDataEventType)eventType; +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query; +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue; +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path; +/** + * Used to figure out what event registration match the event registration that + * needs to be removed. + */ +- (BOOL)matches:(id)other; +@property(nonatomic, readonly) FIRDatabaseHandle handle; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h new file mode 100644 index 00000000..d4dca60d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FEventRegistration.h" + +/** + * A singleton event registration to mark a query as keep synced + */ +@interface FKeepSyncedEventRegistration : NSObject + ++ (FKeepSyncedEventRegistration *)instance; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m new file mode 100644 index 00000000..1821829f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeepSyncedEventRegistration.h" + +@interface FKeepSyncedEventRegistration () + +@end + +@implementation FKeepSyncedEventRegistration + ++ (FKeepSyncedEventRegistration *)instance { + static dispatch_once_t onceToken; + static FKeepSyncedEventRegistration *keepSynced; + dispatch_once(&onceToken, ^{ + keepSynced = [[FKeepSyncedEventRegistration alloc] init]; + }); + return keepSynced; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return NO; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never create event for FKeepSyncedEventRegistration"]; + return nil; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never raise event for FKeepSyncedEventRegistration"]; +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + // Don't create cancel events.... + return nil; +} + +- (FIRDatabaseHandle)handle { + // TODO[offline]: returning arbitray, can't return NSNotFound since that is + // used to match other event registrations We should really redo this to + // match on different kind of events (single observer, all observers, + // cancelled) rather than on a NSNotFound handle... + return NSNotFound - 1; +} + +- (BOOL)matches:(id)other { + // Only matches singleton instance + return self == other; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h new file mode 100644 index 00000000..819febec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FValueEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +@property(nonatomic, copy, readonly) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m new file mode 100644 index 00000000..21cf3155 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FValueEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FValueEventRegistration + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callback = callbackBlock; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return eventType == FIRDataEventTypeValue; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:query.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:FIRDataEventTypeValue + eventRegistration:self + dataSnapshot:snapshot]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB065001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callback != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB065002", @"Raising value event on %@", + dataEvent.snapshot.key); + dispatch_async(queue, ^{ + self.callback(dataEvent.snapshot); + }); + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h new file mode 100644 index 00000000..0b4b9d89 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@protocol FOperation; +@protocol FEventRegistration; +@class FWriteTreeRef; +@class FQuerySpec; +@class FChange; +@class FPath; +@class FViewCache; + +@interface FViewOperationResult : NSObject + +@property(nonatomic, strong, readonly) NSArray *changes; +@property(nonatomic, strong, readonly) NSArray *events; + +@end + +@interface FView : NSObject + +@property(nonatomic, strong, readonly) FQuerySpec *query; + +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache; + +- (id)eventCache; +- (id)serverCache; +- (id)completeServerCacheFor:(FPath *)path; +- (BOOL)isEmpty; + +- (void)addEventRegistration:(id)eventRegistration; +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError; + +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; +- (NSArray *)initialEvents:(id)registration; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m new file mode 100644 index 00000000..a15e13d9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FView.h" +#import "FCacheNode.h" +#import "FCancelEvent.h" +#import "FEmptyNode.h" +#import "FEventGenerator.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FViewCache.h" +#import "FViewProcessor.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +@interface FViewOperationResult () + +@property(nonatomic, strong, readwrite) NSArray *changes; +@property(nonatomic, strong, readwrite) NSArray *events; + +@end + +@implementation FViewOperationResult + +- (id)initWithChanges:(NSArray *)changes events:(NSArray *)events { + self = [super init]; + if (self != nil) { + self->_changes = changes; + self->_events = events; + } + return self; +} + +@end + +/** + * A view represents a specific location and query that has 1 or more event + * registrations. + * + * It does several things: + * - Maintains the list of event registration for this location/query. + * - Maintains a cache of the data visible for this location/query. + * - Applies new operations (via applyOperation), updates the cache, and based + * on the event registrations returns the set of events to be raised. + */ +@interface FView () + +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, strong) FViewProcessor *processor; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) NSMutableArray *eventRegistrations; +@property(nonatomic, strong) FEventGenerator *eventGenerator; + +@end + +@implementation FView +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache { + self = [super init]; + if (self) { + self.query = query; + + FIndexedFilter *indexFilter = + [[FIndexedFilter alloc] initWithIndex:query.index]; + id filter = query.params.nodeFilter; + self.processor = [[FViewProcessor alloc] initWithFilter:filter]; + FCacheNode *initialServerCache = initialViewCache.cachedServerSnap; + FCacheNode *initialEventCache = initialViewCache.cachedEventSnap; + + // Don't filter server node with other filter than index, wait for + // tagged listen + FIndexedNode *emptyIndexedNode = + [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:query.index]; + FIndexedNode *serverSnap = + [indexFilter updateFullNode:emptyIndexedNode + withNewNode:initialServerCache.indexedNode + accumulator:nil]; + FIndexedNode *eventSnap = + [filter updateFullNode:emptyIndexedNode + withNewNode:initialEventCache.indexedNode + accumulator:nil]; + FCacheNode *newServerCache = [[FCacheNode alloc] + initWithIndexedNode:serverSnap + isFullyInitialized:initialServerCache.isFullyInitialized + isFiltered:indexFilter.filtersNodes]; + FCacheNode *newEventCache = [[FCacheNode alloc] + initWithIndexedNode:eventSnap + isFullyInitialized:initialEventCache.isFullyInitialized + isFiltered:filter.filtersNodes]; + + self.viewCache = [[FViewCache alloc] initWithEventCache:newEventCache + serverCache:newServerCache]; + + self.eventRegistrations = [[NSMutableArray alloc] init]; + + self.eventGenerator = [[FEventGenerator alloc] initWithQuery:query]; + } + + return self; +} + +- (id)serverCache { + return self.viewCache.cachedServerSnap.node; +} + +- (id)eventCache { + return self.viewCache.cachedEventSnap.node; +} + +- (id)completeServerCacheFor:(FPath *)path { + id cache = self.viewCache.completeServerSnap; + if (cache) { + // If this isn't a "loadsAllData" view, then cache isn't actually a + // complete cache and we need to see if it contains the child we're + // interested in. + if ([self.query loadsAllData] || + (!path.isEmpty && + ![cache getImmediateChild:path.getFront].isEmpty)) { + return [cache getChild:path]; + } + } + return nil; +} + +- (BOOL)isEmpty { + return self.eventRegistrations.count == 0; +} + +- (void)addEventRegistration:(id)eventRegistration { + [self.eventRegistrations addObject:eventRegistration]; +} + +/** + * @param eventRegistration If null, remove all callbacks. + * @param cancelError If a cancelError is provided, appropriate cancel events + * will be returned. + * @return Cancel events, if cancelError was provided. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError { + NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + if (cancelError != nil) { + NSAssert(eventRegistration == nil, + @"A cancel should cancel all event registrations."); + FPath *path = self.query.path; + for (id registration in self.eventRegistrations) { + FCancelEvent *maybeEvent = + [registration createCancelEventFromError:cancelError path:path]; + if (maybeEvent) { + [cancelEvents addObject:maybeEvent]; + } + } + } + + if (eventRegistration) { + NSUInteger i = 0; + while (i < self.eventRegistrations.count) { + id existing = self.eventRegistrations[i]; + if ([existing matches:eventRegistration]) { + [self.eventRegistrations removeObjectAtIndex:i]; + } else { + i++; + } + } + } else { + [self.eventRegistrations removeAllObjects]; + } + return cancelEvents; +} + +/** + * Applies the given Operation, updates our cache, and returns the appropriate + * events and changes + */ +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + if (operation.type == FOperationTypeMerge && + operation.source.queryParams != nil) { + NSAssert(self.viewCache.completeServerSnap != nil, + @"We should always have a full cache before handling merges"); + NSAssert(self.viewCache.completeEventSnap != nil, + @"Missing event cache, even though we have a server cache"); + } + FViewCache *oldViewCache = self.viewCache; + FViewProcessorResult *result = + [self.processor applyOperationOn:oldViewCache + operation:operation + writesCache:writesCache + completeCache:optCompleteServerCache]; + + NSAssert(result.viewCache.cachedServerSnap.isFullyInitialized || + !oldViewCache.cachedServerSnap.isFullyInitialized, + @"Once a server snap is complete, it should never go back."); + + self.viewCache = result.viewCache; + NSArray *events = [self + generateEventsForChanges:result.changes + eventCache:result.viewCache.cachedEventSnap.indexedNode + registration:nil]; + return [[FViewOperationResult alloc] initWithChanges:result.changes + events:events]; +} + +- (NSArray *)initialEvents:(id)registration { + FCacheNode *eventSnap = self.viewCache.cachedEventSnap; + NSMutableArray *initialChanges = [[NSMutableArray alloc] init]; + [eventSnap.indexedNode.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:node]; + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:indexed + childKey:key]; + [initialChanges addObject:change]; + }]; + if (eventSnap.isFullyInitialized) { + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + [initialChanges addObject:change]; + } + return [self generateEventsForChanges:initialChanges + eventCache:eventSnap.indexedNode + registration:registration]; +} + +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + registration:(id)registration { + NSArray *registrations; + if (registration == nil) { + registrations = [[NSArray alloc] initWithArray:self.eventRegistrations]; + } else { + registrations = [[NSArray alloc] initWithObjects:registration, nil]; + } + return [self.eventGenerator generateEventsForChanges:changes + eventCache:eventCache + eventRegistrations:registrations]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FView (%@)", self.query]; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h new file mode 100644 index 00000000..62618d2b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h @@ -0,0 +1,40 @@ +#/* +* Copyright 2017 Google +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#import + +@protocol FNode; +@class FCacheNode; +@class FIndexedNode; + +@interface FViewCache : NSObject + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache; + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; + +@property(nonatomic, strong, readonly) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readonly) id completeEventSnap; +@property(nonatomic, strong, readonly) FCacheNode *cachedServerSnap; +@property(nonatomic, strong, readonly) id completeServerSnap; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m new file mode 100644 index 00000000..13e9283d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewCache.h" +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FNode.h" + +@interface FViewCache () +@property(nonatomic, strong, readwrite) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readwrite) FCacheNode *cachedServerSnap; +@end + +@implementation FViewCache + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache { + self = [super init]; + if (self) { + self.cachedEventSnap = eventCache; + self.cachedServerSnap = serverCache; + } + return self; +} + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedEventCache = + [[FCacheNode alloc] initWithIndexedNode:eventSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:updatedEventCache + serverCache:self.cachedServerSnap]; +} + +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedServerCache = + [[FCacheNode alloc] initWithIndexedNode:serverSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:self.cachedEventSnap + serverCache:updatedServerCache]; +} + +- (id)completeEventSnap { + return (self.cachedEventSnap.isFullyInitialized) ? self.cachedEventSnap.node + : nil; +} + +- (id)completeServerSnap { + return (self.cachedServerSnap.isFullyInitialized) + ? self.cachedServerSnap.node + : nil; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h new file mode 100644 index 00000000..bf25163c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FChange; + +@interface FChildChangeAccumulator : NSObject + +- (id)init; +- (void)trackChildChange:(FChange *)change; +- (NSArray *)changes; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m new file mode 100644 index 00000000..e35c2e2d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildChangeAccumulator.h" +#import "FChange.h" +#import "FIndex.h" + +@interface FChildChangeAccumulator () +@property(nonatomic, strong) NSMutableDictionary *changeMap; +@end + +@implementation FChildChangeAccumulator + +- (id)init { + self = [super init]; + if (self) { + self.changeMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)trackChildChange:(FChange *)change { + FIRDataEventType type = change.type; + NSString *childKey = change.childKey; + NSAssert(type == FIRDataEventTypeChildAdded || + type == FIRDataEventTypeChildChanged || + type == FIRDataEventTypeChildRemoved, + @"Only child changes supported for tracking."); + NSAssert(![change.childKey isEqualToString:@".priority"], + @"Changes not tracked on priority"); + if (self.changeMap[childKey] != nil) { + FChange *oldChange = [self.changeMap objectForKey:childKey]; + FIRDataEventType oldType = oldChange.type; + if (type == FIRDataEventTypeChildAdded && + oldType == FIRDataEventTypeChildRemoved) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.indexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildAdded) { + [self.changeMap removeObjectForKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildRemoved + indexedNode:oldChange.oldIndexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildAdded) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:change.indexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.oldIndexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else { + NSString *reason = [NSString + stringWithFormat: + @"Illegal combination of changes: %@ occurred after %@", + change, oldChange]; + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:reason + userInfo:nil]; + } + } else { + [self.changeMap setObject:change forKey:childKey]; + } +} + +- (NSArray *)changes { + return [self.changeMap allValues]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h new file mode 100644 index 00000000..0c04bc14 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FNamedNode; +@protocol FIndex; + +@protocol FCompleteChildSource + +- (id)completeChild:(NSString *)childKey; +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h new file mode 100644 index 00000000..291e79af --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@protocol FIndex; + +@interface FIndexedFilter : NSObject + +- (id)initWithIndex:(id)theIndex; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m new file mode 100644 index 00000000..f49af79e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m @@ -0,0 +1,164 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FIndexedNode.h" +#import "FKeyIndex.h" +#import "FNode.h" + +@interface FIndexedFilter () +@property(nonatomic, strong, readwrite) id index; +@end + +@implementation FIndexedFilter +- (id)initWithIndex:(id)theIndex { + self = [super init]; + if (self) { + self.index = theIndex; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)indexedNode + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert([indexedNode hasIndex:self.index], + @"The index in FIndexedNode must match the index of the filter"); + id node = indexedNode.node; + id oldChildSnap = [node getImmediateChild:childKey]; + + // Check if anything actually changed. + if ([[oldChildSnap getChild:affectedPath] + isEqual:[newChildSnap getChild:affectedPath]]) { + // There's an edge case where a child can enter or leave the view + // because affectedPath was set to null. In this case, affectedPath will + // appear null in both the old and new snapshots. So we need to avoid + // treating these cases as "nothing changed." + if (oldChildSnap.isEmpty == newChildSnap.isEmpty) { +// Nothing changed. +#ifdef DEBUG + NSAssert([oldChildSnap isEqual:newChildSnap], + @"Old and new snapshots should be equal."); +#endif + + return indexedNode; + } + } + if (optChangeAccumulator) { + if (newChildSnap.isEmpty) { + if ([node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + NSAssert(node.isLeafNode, + @"A child remove without an old child only makes " + @"sense on a leaf node."); + } + } else if (oldChildSnap.isEmpty) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } + if (node.isLeafNode && newChildSnap.isEmpty) { + return indexedNode; + } else { + return [indexedNode updateChild:childKey withNewChild:newChildSnap]; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (optChangeAccumulator) { + [oldSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if (![newSnap.node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if ([oldSnap.node hasChild:childKey]) { + id oldChildSnap = + [oldSnap.node getImmediateChild:childKey]; + if (![oldChildSnap isEqual:childNode]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:childNode] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + } + return newSnap; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + if ([oldSnap.node isEmpty]) { + return oldSnap; + } else { + return [oldSnap updatePriority:priority]; + } +} + +- (BOOL)filtersNodes { + return NO; +} + +- (id)indexedFilter { + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h new file mode 100644 index 00000000..0642e724 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; + +@interface FLimitedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m new file mode 100644 index 00000000..fab9aab1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m @@ -0,0 +1,285 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLimitedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FQueryParams.h" +#import "FRangedFilter.h" +#import "FTreeSortedDictionary.h" + +@interface FLimitedFilter () +@property(nonatomic, strong) FRangedFilter *rangedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic) NSInteger limit; +@property(nonatomic) BOOL reverse; + +@end + +@implementation FLimitedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.rangedFilter = [[FRangedFilter alloc] initWithQueryParams:params]; + self.index = params.index; + self.limit = params.limit; + self.reverse = !params.isViewFromLeft; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self.rangedFilter matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + if ([[oldSnap.node getImmediateChild:childKey] isEqual:newChildSnap]) { + // No change + return oldSnap; + } else if (oldSnap.node.numChildren < self.limit) { + return [[self.rangedFilter indexedFilter] + updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; + } else { + return [self fullLimitUpdateNode:oldSnap + forChildKey:childKey + newChild:newChildSnap + fromSource:source + accumulator:optChangeAccumulator]; + } +} + +- (FIndexedNode *)fullLimitUpdateNode:(FIndexedNode *)oldIndexed + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert(oldIndexed.node.numChildren == self.limit, + @"Should have number of children equal to limit."); + + FNamedNode *windowBoundary = + self.reverse ? oldIndexed.firstChild : oldIndexed.lastChild; + + BOOL inRange = [self.rangedFilter matchesKey:childKey andNode:newChildSnap]; + if ([oldIndexed.node hasChild:childKey]) { + // `childKey` was already in `oldSnap`. Figure out if it remains in the + // window or needs to be replaced. + id oldChildSnap = [oldIndexed.node getImmediateChild:childKey]; + + // In case the `newChildSnap` falls outside the window, get the + // `nextChild` that might replace it. + FNamedNode *nextChild = [source childByIndex:self.index + afterChild:windowBoundary + isReverse:(BOOL)self.reverse]; + if (nextChild != nil && ([nextChild.name isEqualToString:childKey] || + [oldIndexed.node hasChild:nextChild.name])) { + // There is a weird edge case where a node is updated as part of a + // merge in the write tree, but hasn't been applied to the limited + // filter yet. Ignore this next child which will be updated later in + // the limited filter... + nextChild = [source childByIndex:self.index + afterChild:nextChild + isReverse:self.reverse]; + } + + // Figure out if `newChildSnap` is in range and ordered before + // `nextChild` + BOOL remainsInWindow = inRange && !newChildSnap.isEmpty; + remainsInWindow = remainsInWindow && + (!nextChild || [self.index compareKey:nextChild.name + andNode:nextChild.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= + NSOrderedSame); + if (remainsInWindow) { + // `newChildSnap` is ordered before `nextChild`, so it's a child + // changed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + return [oldIndexed updateChild:childKey withNewChild:newChildSnap]; + } else { + // `newChildSnap` is ordered after `nextChild`, so it's a child + // removed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + FIndexedNode *newIndexed = + [oldIndexed updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + + // We need to check if the `nextChild` is actually in range before + // adding it + BOOL nextChildInRange = + (nextChild != nil) && + [self.rangedFilter matchesKey:nextChild.name + andNode:nextChild.node]; + if (nextChildInRange) { + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode + indexedNodeWithNode:nextChild.node] + childKey:nextChild.name]; + [optChangeAccumulator trackChildChange:change]; + } + return [newIndexed updateChild:nextChild.name + withNewChild:nextChild.node]; + } else { + return newIndexed; + } + } + } else if (newChildSnap.isEmpty) { + // We're deleting a node, but it was not in the window, so ignore it. + return oldIndexed; + } else if (inRange) { + // `newChildSnap` is in range, but was ordered after `windowBoundary`. + // If this has changed, we bump out the `windowBoundary` and add the + // `newChildSnap` + if ([self.index compareKey:windowBoundary.name + andNode:windowBoundary.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= NSOrderedSame) { + if (optChangeAccumulator != nil) { + FChange *removedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode + indexedNodeWithNode:windowBoundary.node] + childKey:windowBoundary.name]; + FChange *addedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:removedChange]; + [optChangeAccumulator trackChildChange:addedChange]; + } + return [[oldIndexed updateChild:childKey withNewChild:newChildSnap] + updateChild:windowBoundary.name + withNewChild:[FEmptyNode emptyNode]]; + } else { + return oldIndexed; + } + } else { + // `newChildSnap` was not in range and remains not in range, so ignore + // it. + return oldIndexed; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode || newSnap.node.isEmpty) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + filtered = newSnap; + // Don't support priorities on queries. + filtered = [filtered updatePriority:[FEmptyNode emptyNode]]; + FNamedNode *startPost = nil; + FNamedNode *endPost = nil; + if (self.reverse) { + startPost = self.rangedFilter.endPost; + endPost = self.rangedFilter.startPost; + } else { + startPost = self.rangedFilter.startPost; + endPost = self.rangedFilter.endPost; + } + __block BOOL foundStartPost = NO; + __block NSUInteger count = 0; + [newSnap + enumerateChildrenReverse:self.reverse + usingBlock:^(NSString *childKey, id childNode, + BOOL *stop) { + if (!foundStartPost && + [self.index + compareKey:startPost.name + andNode:startPost.node + toOtherKey:childKey + andNode:childNode + reverse:self.reverse] <= NSOrderedSame) { + // Start adding + foundStartPost = YES; + } + BOOL inRange = foundStartPost && count < self.limit; + inRange = inRange && + [self.index compareKey:childKey + andNode:childNode + toOtherKey:endPost.name + andNode:endPost.node + reverse:self.reverse] <= + NSOrderedSame; + if (inRange) { + count++; + } else { + filtered = [filtered + updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries. + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +- (id)indexedFilter { + return self.rangedFilter.indexedFilter; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h new file mode 100644 index 00000000..d19c6fb9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@protocol FCompleteChildSource; +@class FChildChangeAccumulator; +@protocol FIndex; +@class FPath; + +/** + * FNodeFilter is used to update nodes and complete children of nodes while + * applying queries on the fly and keeping track of any child changes. This + * class does not track value changes as value changes depend on more than just + * the node itself. Different kind of queries require different kind of + * implementations of this interface. + */ +@protocol FNodeFilter + +/** + * Update a single complete child in the snap. If the child equals the old child + * in the snap, this is a no-op. The method expects an indexed snap. + */ +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator:(FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update a node in full and output any resulting change from this complete + * update. + */ +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update the priority of the root node + */ +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap; + +/** + * Returns true if children might be filtered due to query critiera + */ +- (BOOL)filtersNodes; + +/** + * Returns the index filter that this filter uses to get a NodeFilter that + * doesn't filter any children. + */ +@property(nonatomic, strong, readonly) id indexedFilter; + +/** + * Returns the index that this filter uses + */ +@property(nonatomic, strong, readonly) id index; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.h new file mode 100644 index 00000000..e85cb2a5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FClock + +- (NSTimeInterval)currentTime; + +@end + +@interface FSystemClock : NSObject + ++ (FSystemClock *)clock; + +@end + +@interface FOffsetClock : NSObject + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.m new file mode 100644 index 00000000..5d9a9ecd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FClock.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" + +@implementation FSystemClock + +- (NSTimeInterval)currentTime { + return [[NSDate date] timeIntervalSince1970]; +} + ++ (FSystemClock *)clock { + static dispatch_once_t onceToken; + static FSystemClock *clock; + dispatch_once(&onceToken, ^{ + clock = [[FSystemClock alloc] init]; + }); + return clock; +} + +@end + +@interface FOffsetClock () + +@property(nonatomic, strong) id clock; +@property(nonatomic) NSTimeInterval offset; + +@end + +@implementation FOffsetClock + +- (NSTimeInterval)currentTime { + return [self.clock currentTime] + self.offset; +} + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset { + self = [super init]; + if (self != nil) { + self->_clock = clock; + self->_offset = offset; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h new file mode 100644 index 00000000..443664ec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; +@class FIndexedNode; +@protocol FNode; + +@interface FEventGenerator : NSObject +- (id)initWithQuery:(FQuerySpec *)query; +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m new file mode 100644 index 00000000..162b0ac3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m @@ -0,0 +1,169 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventGenerator.h" +#import "FChange.h" +#import "FDataEvent.h" +#import "FEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" + +@interface FEventGenerator () +@property(nonatomic, strong) FQuerySpec *query; +@end + +/** + * An EventGenerator is used to convert "raw" changes (fb.core.view.Change) as + * computed by the CacheDiffer into actual events (fb.core.view.Event) that can + * be raised. See generateEventsForChanges() for details. + */ +@implementation FEventGenerator + +- (id)initWithQuery:(FQuerySpec *)query { + self = [super init]; + if (self) { + self.query = query; + } + return self; +} + +/** + * Given a set of raw changes (no moved events, and prevName not specified yet), + * and a set of EventRegistrations that should be notified of these changes, + * generate the actual events to be raised. + * + * Notes: + * - child_moved events will be synthesized at this time for any child_changed + * events that affect our index + * - prevName will be calculated based on the index ordering + * + * @param changes NSArray of FChange, not necessarily in order. + * @param registrations is NSArray of FEventRegistration. + * @return NSArray of FEvent. + */ +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *events = [[NSMutableArray alloc] init]; + + // child_moved is index-specific, so check all our child_changed events to + // see if we need to materialize child_moved events with this view's index + NSMutableArray *moves = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == FIRDataEventTypeChildChanged && + [self.query.index + indexedValueChangedBetween:change.oldIndexedNode.node + and:change.indexedNode.node]) { + FChange *moveChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildMoved + indexedNode:change.indexedNode + childKey:change.childKey + oldIndexedNode:nil]; + [moves addObject:moveChange]; + } + } + + [self generateEvents:events + forType:FIRDataEventTypeChildRemoved + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildAdded + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildMoved + changes:moves + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildChanged + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeValue + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + + return events; +} + +- (void)generateEvents:(NSMutableArray *)events + forType:(FIRDataEventType)eventType + changes:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *filteredChanges = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == eventType) { + [filteredChanges addObject:change]; + } + } + + id index = self.query.index; + + [filteredChanges + sortUsingComparator:^NSComparisonResult(FChange *one, FChange *two) { + if (one.childKey == nil || two.childKey == nil) { + @throw [[NSException alloc] + initWithName:@"InternalInconsistencyError" + reason:@"Should only compare child_ events" + userInfo:nil]; + } + return [index compareKey:one.childKey + andNode:one.indexedNode.node + toOtherKey:two.childKey + andNode:two.indexedNode.node]; + }]; + + for (FChange *change in filteredChanges) { + for (id registration in registrations) { + if ([registration responseTo:eventType]) { + id event = [self generateEventForChange:change + registration:registration + eventCache:eventCache]; + [events addObject:event]; + } + } + } +} + +- (id)generateEventForChange:(FChange *)change + registration:(id)registration + eventCache:(FIndexedNode *)eventCache { + FChange *materializedChange; + if (change.type == FIRDataEventTypeValue || + change.type == FIRDataEventTypeChildRemoved) { + materializedChange = change; + } else { + NSString *prevChildKey = + [eventCache predecessorForChildKey:change.childKey + childNode:change.indexedNode.node + index:self.query.index]; + materializedChange = [change changeWithPrevKey:prevChildKey]; + } + return [registration createEventFrom:materializedChange query:self.query]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h new file mode 100644 index 00000000..6df83424 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig.h" + +@protocol FStorageEngine; + +@interface FIRDatabaseConfig () + +@property(nonatomic, readonly) BOOL isFrozen; +@property(nonatomic, strong, readonly) NSString *sessionIdentifier; +@property(nonatomic, strong, readonly) NSString *googleAppID; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) id forceStorageEngine; + +- (void)freeze; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m new file mode 100644 index 00000000..9e557446 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m @@ -0,0 +1,527 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIRDatabase.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FNextPushId.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@implementation FIRDatabaseReference + +#pragma mark - +#pragma mark Constructors + +- (id)initWithConfig:(FIRDatabaseConfig *)config { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:[[FIRApp defaultApp] options].databaseURL]; + [FValidation validateFrom:@"initWithUrl:" validURL:parsedUrl]; + return [self initWithRepo:[FRepoManager getRepo:parsedUrl.repoInfo + config:config] + path:parsedUrl.path]; +} + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path { + return [super initWithRepo:repo + path:path + params:[FQueryParams defaultInstance] + orderByCalled:NO + priorityMethodCalled:NO]; +} + +#pragma mark - +#pragma mark Ancillary methods + +- (nullable NSString *)key { + if ([self.path isEmpty]) { + return nil; + } else { + return [self.path getBack]; + } +} + +- (FIRDatabase *)database { + return self.repo.database; +} + +- (FIRDatabaseReference *)parent { + FPath *parentPath = [self.path parent]; + FIRDatabaseReference *parent = nil; + if (parentPath != nil) { + parent = [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parentPath]; + } + return parent; +} + +- (NSString *)URL { + FIRDatabaseReference *parent = [self parent]; + return parent == nil + ? [self.repo description] + : [NSString + stringWithFormat:@"%@/%@", [parent description], + [FStringUtilities urlEncoded:self.key]]; +} + +- (NSString *)description { + return [self URL]; +} + +- (FIRDatabaseReference *)root { + return [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[[FPath alloc] initWith:@""]]; +} + +#pragma mark - +#pragma mark Child methods + +- (FIRDatabaseReference *)child:(NSString *)pathString { + if ([self.path getFront] == nil) { + // we're at the root + [FValidation validateFrom:@"child:" validRootPathString:pathString]; + } else { + [FValidation validateFrom:@"child:" validPathString:pathString]; + } + FPath *path = [self.path childFromString:pathString]; + FIRDatabaseReference *firebaseRef = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:path]; + return firebaseRef; +} + +- (FIRDatabaseReference *)childByAutoId { + [FValidation validateFrom:@"childByAutoId:" writablePath:self.path]; + + NSString *name = [FNextPushId get:self.repo.serverTime]; + return [self child:name]; +} + +#pragma mark - +#pragma mark Basic write methods + +- (void)setValue:(id)value { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"setValue:"]; +} + +- (void)setValue:(id)value withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"setValue:withCompletionBlock:"]; +} + +- (void)setValue:(id)value andPriority:(id)priority { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"setValue:andPriority:"]; +} + +- (void)setValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"setValue:andPriority:withCompletionBlock:"]; +} + +- (void)setValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + id newNode = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:self.path withNode:newNode withCallback:userCallback]; + }); +} + +- (void)removeValue { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"removeValue:"]; +} + +- (void)removeValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"removeValueWithCompletionBlock:"]; +} + +- (void)setPriority:(id)priority { + [self setPriorityInternal:priority + withCompletionBlock:nil + from:@"setPriority:"]; +} + +- (void)setPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + + [self setPriorityInternal:priority + withCompletionBlock:block + from:@"setPriority:withCompletionBlock:"]; +} + +- (void)setPriorityInternal:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:[self.path childFromString:@".priority"] + withNode:[FSnapshotUtilities nodeFrom:priority] + withCallback:userCallback]; + }); +} + +- (void)updateChildValues:(NSDictionary *)values { + [self updateChildValuesInternal:values + withCompletionBlock:nil + from:@"updateChildValues:"]; +} + +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self updateChildValuesInternal:values + withCompletionBlock:block + from:@"updateChildValues:withCompletionBlock:"]; +} + +- (void)updateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo update:self.path withNodes:merge withCallback:userCallback]; + }); +} + +#pragma mark - +#pragma mark Disconnect Operations + +- (void)onDisconnectSetValue:(id)value { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectSetValue:"]; +} + +- (void)onDisconnectSetValue:(id)value + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectSetValue:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValue:(id)value andPriority:(id)priority { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"onDisconnectSetValue:andPriority:"]; +} + +- (void)onDisconnectSetValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"onDisconnectSetValue:andPriority:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + id newNodeUnresolved = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectSet:self.path + withNode:newNodeUnresolved + withCallback:userCallback]; + }); +} + +- (void)onDisconnectRemoveValue { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectRemoveValue:"]; +} + +- (void)onDisconnectRemoveValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectRemoveValueWithCompletionB" + @"lock:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values { + [self + onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:nil + from: + @"onDisconnectUpdateChildValues:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:block + from:@"onDisconnectUpdateChildValues" + @":withCompletionBlock:"]; +} + +- (void)onDisconnectUpdateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectUpdate:self.path + withNodes:merge + withCallback:userCallback]; + }); +} + +- (void)cancelDisconnectOperations { + [self cancelDisconnectOperationsWithCompletionBlock:nil]; +} + +- (void)cancelDisconnectOperationsWithCompletionBlock: + (fbt_void_nserror_ref)block { + fbt_void_nserror_ref callback = nil; + if (block != nil) { + callback = [block copy]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectCancel:self.path withCallback:callback]; + }); +} + +#pragma mark - +#pragma mark Connection management methods + ++ (void)goOffline { + [FRepoManager interruptAll]; +} + ++ (void)goOnline { + [FRepoManager resumeAll]; +} + +#pragma mark - +#pragma mark Data reading methods deferred to FQuery + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + [super removeObserverWithHandle:handle]; +} + +- (void)removeAllObservers { + [super removeAllObservers]; +} + +- (void)keepSynced:(BOOL)keepSynced { + [super keepSynced:keepSynced]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +#pragma mark - +#pragma mark Query methods +// These methods suppress warnings from having method definitions in +// FIRDatabaseReference.h for docs generation. + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + return [super queryLimitedToFirst:limit]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + return [super queryLimitedToLast:limit]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key { + return [super queryOrderedByChild:key]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + return [super queryOrderedByKey]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + return [super queryOrderedByPriority]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [super queryStartingAtValue:startValue]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + return [super queryStartingAtValue:startValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [super queryEndingAtValue:endValue]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + return [super queryEndingAtValue:endValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [super queryEqualToValue:value]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + return [super queryEqualToValue:value childKey:childKey]; +} + +#pragma mark - +#pragma mark Transaction methods + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block { + [FValidation validateFrom:@"runTransactionBlock:" writablePath:self.path]; + [self runTransactionBlock:block andCompletionBlock:nil withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)update + andCompletionBlock: + (fbt_void_nserror_bool_datasnapshot)completionBlock { + [FValidation validateFrom:@"runTransactionBlock:andCompletionBlock:" + writablePath:self.path]; + [self runTransactionBlock:update + andCompletionBlock:completionBlock + withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block + andCompletionBlock:(fbt_void_nserror_bool_datasnapshot)completionBlock + withLocalEvents:(BOOL)localEvents { + [FValidation + validateFrom:@"runTransactionBlock:andCompletionBlock:withLocalEvents:" + writablePath:self.path]; + fbt_transactionresult_mutabledata updateCopy = [block copy]; + fbt_void_nserror_bool_datasnapshot onCompleteCopy = [completionBlock copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo startTransactionOnPath:self.path + update:updateCopy + onComplete:onCompleteCopy + withLocalEvents:localEvents]; + }); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.h new file mode 100644 index 00000000..89bec767 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableSortedDictionary; +@class FNamedNode; +@protocol FNode; + +@protocol FIndex +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2; + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse; + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2; + +- (BOOL)isDefinedOn:(id)node; +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode; +- (FNamedNode *)minPost; +- (FNamedNode *)maxPost; +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name; +- (NSString *)queryDefinition; + +@end + +@interface FIndex : NSObject + ++ (id)indexFromQueryDefinition:(NSString *)string; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.m new file mode 100644 index 00000000..03663994 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FIndex.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" + +#import "FKeyIndex.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FValueIndex.h" + +@implementation FIndex + ++ (id)indexFromQueryDefinition:(NSString *)string { + if ([string isEqualToString:@".key"]) { + return [FKeyIndex keyIndex]; + } else if ([string isEqualToString:@".value"]) { + return [FValueIndex valueIndex]; + } else if ([string isEqualToString:@".priority"]) { + return [FPriorityIndex priorityIndex]; + } else { + return + [[FPathIndex alloc] initWithPath:[[FPath alloc] initWith:string]]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h new file mode 100644 index 00000000..281a5ac4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FKeyIndex : NSObject ++ (id)keyIndex; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m new file mode 100644 index 00000000..ac108299 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeyIndex.h" +#import "FEmptyNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FKeyIndex () + +@property(nonatomic, strong) FNamedNode *maxPost; + +@end + +@implementation FKeyIndex + +- (id)init { + self = [super init]; + if (self) { + self.maxPost = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FEmptyNode emptyNode]]; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + return [FUtilities compareKey:key1 toKey:key2]; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return NO; // The key for a node never changes. +} + +- (FNamedNode *)minPost { + return [FNamedNode min]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + NSString *key = indexValue.val; + NSAssert([key isKindOfClass:[NSString class]], + @"KeyIndex indexValue must always be a string."); + // We just use empty node, but it'll never be compared, since our comparator + // only looks at name. + return [[FNamedNode alloc] initWithName:key andNode:[FEmptyNode emptyNode]]; +} + +- (NSString *)queryDefinition { + return @".key"; +} + +- (NSString *)description { + return @"FKeyIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".key" hash]; +} + ++ (id)keyIndex { + static id keyIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + keyIndex = [[FKeyIndex alloc] init]; + }); + return keyIndex; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h new file mode 100644 index 00000000..99aabf89 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" +#import + +@interface FListenComplete : NSObject + +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, readonly) FOperationType type; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m new file mode 100644 index 00000000..26370c6a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenComplete.h" +#import "FOperationSource.h" +#import "FPath.h" + +@interface FListenComplete () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, readwrite) FOperationType type; +@end + +@implementation FListenComplete +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath { + NSAssert(!aSource.fromUser, + @"Can't have a listen complete from a user source"); + self = [super init]; + if (self) { + self.source = aSource; + self.path = aPath; + self.type = FOperationTypeListenComplete; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FListenComplete alloc] initWithSource:self.source + path:[FPath empty]]; + } else { + return [[FListenComplete alloc] initWithSource:self.source + path:[self.path popFront]]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FListenComplete { path=%@, source=%@ }", + self.path, self.source]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h new file mode 100644 index 00000000..c68137e3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import + +@interface FMaxNode : FChildrenNode ++ (id)maxNode; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m new file mode 100644 index 00000000..28e7672b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMaxNode.h" +#import "FEmptyNode.h" +#import "FUtilities.h" + +@implementation FMaxNode { +} +- (id)init { + self = [super init]; + if (self) { + } + return self; +} + ++ (id)maxNode { + static FMaxNode *maxNode = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + maxNode = [[FMaxNode alloc] init]; + }); + return maxNode; +} + +- (NSComparisonResult)compare:(id)other { + if (other == self) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + +- (BOOL)isEqual:(id)other { + return other == self; +} + +- (id)getImmediateChild:(NSString *)childName { + return [FEmptyNode emptyNode]; +} + +- (BOOL)isEmpty { + return NO; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h new file mode 100644 index 00000000..4414dfd2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FNamedNode : NSObject + +@property(nonatomic, strong, readonly) NSString *name; +@property(nonatomic, strong, readonly) id node; + +- (id)initWithName:(NSString *)name andNode:(id)node; + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node; + ++ (FNamedNode *)min; ++ (FNamedNode *)max; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m new file mode 100644 index 00000000..3b2eaf72 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNamedNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FMaxNode.h" +#import "FUtilities.h" + +@interface FNamedNode () +@property(nonatomic, strong, readwrite) NSString *name; +@property(nonatomic, strong, readwrite) id node; +@end + +@implementation FNamedNode + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node { + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (id)initWithName:(NSString *)name andNode:(id)node { + self = [super init]; + if (self) { + self.name = name; + self.node = node; + } + return self; +} + +- (id)copy { + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + ++ (FNamedNode *)min { + static FNamedNode *min = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + min = [[FNamedNode alloc] initWithName:[FUtilities minName] + andNode:[FEmptyNode emptyNode]]; + }); + return min; +} + ++ (FNamedNode *)max { + static FNamedNode *max = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + max = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FMaxNode maxNode]]; + }); + return max; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"NamedNode[%@] %@", self.name, self.node]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (object == nil || ![object isKindOfClass:[FNamedNode class]]) { + return NO; + } + + FNamedNode *namedNode = object; + if (![self.name isEqualToString:namedNode.name]) { + return NO; + } + if (![self.node isEqual:namedNode.node]) { + return NO; + } + + return YES; +} + +- (NSUInteger)hash { + NSUInteger nameHash = [self.name hash]; + NSUInteger nodeHash = [self.node hash]; + NSUInteger result = 31 * nameHash + nodeHash; + return result; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h new file mode 100644 index 00000000..6ab91519 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import "FPath.h" +#import + +@interface FPathIndex : NSObject +- (id)initWithPath:(FPath *)path; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m new file mode 100644 index 00000000..214eab8e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m @@ -0,0 +1,135 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPathIndex.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FPathIndex () +@property(nonatomic, strong) FPath *path; +@end + +@implementation FPathIndex + +- (id)initWithPath:(FPath *)path { + self = [super init]; + if (self) { + if (path.isEmpty || [path.getFront isEqualToString:@".priority"]) { + [NSException raise:NSInvalidArgumentException + format:@"Invalid path for PathIndex: %@", path]; + } + _path = path; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getChild:self.path]; + id child2 = [node2 getChild:self.path]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return ![node getChild:self.path].isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getChild:self.path]; + id newValue = [newNode getChild:self.path]; + return [oldValue compare:newValue] != NSOrderedSame; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + id maxNode = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:[FMaxNode maxNode]]; + + return [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:maxNode]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return [self.path wireFormat]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FPathIndex(%@)", self.path]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + if (![other isKindOfClass:[FPathIndex class]]) { + return NO; + } + return ([self.path isEqual:((FPathIndex *)other).path]); +} + +- (NSUInteger)hash { + return [self.path hash]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h new file mode 100644 index 00000000..1b4534ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" + +@interface FPriorityIndex : NSObject ++ (id)priorityIndex; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m new file mode 100644 index 00000000..0b338374 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m @@ -0,0 +1,126 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPriorityIndex.h" + +#import "FEmptyNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FUtilities.h" + +// TODO: Abstract into some common base class? + +@implementation FPriorityIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getPriority]; + id child2 = [node2 getPriority]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return !node.getPriority.isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getPriority]; + id newValue = [newNode getPriority]; + return ![oldValue isEqual:newValue]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return [self makePost:[FMaxNode maxNode] name:[FUtilities maxName]]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FLeafNode alloc] initWithValue:@"[PRIORITY-POST]" + withPriority:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return @".priority"; +} + +- (NSString *)description { + return @"FPriorityIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + return [other isKindOfClass:[FPriorityIndex class]]; +} + +- (NSUInteger)hash { + // chosen by a fair dice roll. Guaranteed to be random + return 3155577; +} + ++ (id)priorityIndex { + static id index; + static dispatch_once_t once; + dispatch_once(&once, ^{ + index = [[FPriorityIndex alloc] init]; + }); + + return index; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h new file mode 100644 index 00000000..3c1aadd6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; +@class FNamedNode; + +@interface FRangedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +- (BOOL)matchesKey:(NSString *)key andNode:(id)node; + +@property(nonatomic, strong, readonly) FNamedNode *startPost; +@property(nonatomic, strong, readonly) FNamedNode *endPost; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m new file mode 100644 index 00000000..bd8ef817 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m @@ -0,0 +1,129 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangedFilter.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FQueryParams.h" + +@interface FRangedFilter () +@property(nonatomic, strong, readwrite) id indexedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic, strong, readwrite) FNamedNode *startPost; +@property(nonatomic, strong, readwrite) FNamedNode *endPost; +@end + +@implementation FRangedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.indexedFilter = + [[FIndexedFilter alloc] initWithIndex:params.index]; + self.index = params.index; + self.startPost = [FRangedFilter startPostFromQueryParams:params]; + self.endPost = [FRangedFilter endPostFromQueryParams:params]; + } + return self; +} + ++ (FNamedNode *)startPostFromQueryParams:(FQueryParams *)params { + if ([params hasStart]) { + NSString *startKey = params.indexStartKey; + return [params.index makePost:params.indexStartValue name:startKey]; + } else { + return params.index.minPost; + } +} + ++ (FNamedNode *)endPostFromQueryParams:(FQueryParams *)params { + if ([params hasEnd]) { + NSString *endKey = params.indexEndKey; + return [params.index makePost:params.indexEndValue name:endKey]; + } else { + return params.index.maxPost; + } +} + +- (BOOL)matchesKey:(NSString *)key andNode:(id)node { + return ([self.index compareKey:self.startPost.name + andNode:self.startPost.node + toOtherKey:key + andNode:node] <= NSOrderedSame && + [self.index compareKey:key + andNode:node + toOtherKey:self.endPost.name + andNode:self.endPost.node] <= NSOrderedSame); +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + return [self.indexedFilter updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + // Dont' support priorities on queries + filtered = [newSnap updatePriority:[FEmptyNode emptyNode]]; + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + if (![self matchesKey:key andNode:node]) { + filtered = [filtered updateChild:key + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h new file mode 100644 index 00000000..25a59b4f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTransformedEnumerator : NSEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform; +- (id)nextObject; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m new file mode 100644 index 00000000..567e1002 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTransformedEnumerator.h" + +@interface FTransformedEnumerator () +@property(nonatomic, strong) NSEnumerator *enumerator; +@property(nonatomic, copy) id (^transform)(id); +@end + +@implementation FTransformedEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform { + self = [super init]; + if (self) { + self.enumerator = enumerator; + self.transform = transform; + } + return self; +} + +- (id)nextObject { + id next = self.enumerator.nextObject; + if (next != nil) { + return self.transform(next); + } else { + return nil; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h new file mode 100644 index 00000000..a79f202f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FValueIndex : NSObject ++ (id)valueIndex; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m new file mode 100644 index 00000000..61021c8b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueIndex.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@implementation FValueIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + NSComparisonResult indexCmp = [node1 compare:node2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return ![oldNode isEqual:newNode]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return FNamedNode.max; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + return [[FNamedNode alloc] initWithName:name andNode:indexValue]; +} + +- (NSString *)queryDefinition { + return @".value"; +} + +- (NSString *)description { + return @"FValueIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".value" hash]; +} + ++ (id)valueIndex { + static id valueIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueIndex = [[FValueIndex alloc] init]; + }); + return valueIndex; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h new file mode 100644 index 00000000..ea6676e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; +@class FViewProcessorResult; +@class FChildChangeAccumulator; +@protocol FNode; +@class FWriteTreeRef; +@class FPath; +@protocol FOperation; +@protocol FNodeFilter; + +@interface FViewProcessor : NSObject + +- (id)initWithFilter:(id)nodeFilter; + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache; +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m new file mode 100644 index 00000000..55249969 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m @@ -0,0 +1,831 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessor.h" +#import "FAckUserWrite.h" +#import "FCacheNode.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FIRDataEventType.h" +#import "FImmutableTree.h" +#import "FKeyIndex.h" +#import "FMerge.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FViewCache.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +/** + * An implementation of FCompleteChildSource that never returns any additional + * children + */ +@interface FNoCompleteChildSource : NSObject +@end + +@implementation FNoCompleteChildSource ++ (FNoCompleteChildSource *)instance { + static FNoCompleteChildSource *source = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + source = [[FNoCompleteChildSource alloc] init]; + }); + return source; +} + +- (id)completeChild:(NSString *)childKey { + return nil; +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + return nil; +} +@end + +/** + * An implementation of FCompleteChildSource that uses a FWriteTree in addition + * to any other server data or old event caches available to calculate complete + * children. + */ +@interface FWriteTreeCompleteChildSource : NSObject +@property(nonatomic, strong) FWriteTreeRef *writes; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) id optCompleteServerCache; +@end + +@implementation FWriteTreeCompleteChildSource +- (id)initWithWrites:(FWriteTreeRef *)writes + viewCache:(FViewCache *)viewCache + serverCache:(id)optCompleteServerCache { + self = [super init]; + if (self) { + self.writes = writes; + self.viewCache = viewCache; + self.optCompleteServerCache = optCompleteServerCache; + } + return self; +} + +- (id)completeChild:(NSString *)childKey { + FCacheNode *node = self.viewCache.cachedEventSnap; + if ([node isCompleteForChild:childKey]) { + return [node.node getImmediateChild:childKey]; + } else { + FCacheNode *serverNode; + if (self.optCompleteServerCache) { + // Since we're only ever getting child nodes, we can use the key + // index here + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:self.optCompleteServerCache + index:[FKeyIndex keyIndex]]; + serverNode = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + serverNode = self.viewCache.cachedServerSnap; + } + return [self.writes calculateCompleteChild:childKey cache:serverNode]; + } +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + id completeServerData = self.optCompleteServerCache != nil + ? self.optCompleteServerCache + : self.viewCache.completeServerSnap; + return [self.writes calculateNextNodeAfterPost:child + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +@end + +@interface FViewProcessor () +@property(nonatomic, strong) id filter; +@end + +@implementation FViewProcessor + +- (id)initWithFilter:(id)nodeFilter { + self = [super init]; + if (self) { + self.filter = nodeFilter; + } + return self; +} + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache { + FChildChangeAccumulator *accumulator = + [[FChildChangeAccumulator alloc] init]; + FViewCache *newViewCache; + + if (operation.type == FOperationTypeOverwrite) { + FOverwrite *overwrite = (FOverwrite *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserOverwriteTo:oldViewCache + changePath:overwrite.path + changedSnap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, + @"Unknown source for overwrite."); + // We filter the node if it's a tagged update or the node has been + // previously filtered and the update is not at the root in which + // case it is ok (and necessary) to mark the node unfiltered again + BOOL filterServerNode = overwrite.source.isTagged || + (oldViewCache.cachedServerSnap.isFiltered && + !overwrite.path.isEmpty); + newViewCache = [self applyServerOverwriteTo:oldViewCache + changePath:overwrite.path + snap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeMerge) { + FMerge *merge = (FMerge *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, @"Unknown source for merge."); + // We filter the node if it's a tagged update or the node has been + // previously filtered + BOOL filterServerNode = merge.source.isTagged || + oldViewCache.cachedServerSnap.isFiltered; + newViewCache = [self applyServerMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeAckUserWrite) { + FAckUserWrite *ackWrite = (FAckUserWrite *)operation; + if (!ackWrite.revert) { + newViewCache = [self ackUserWriteOn:oldViewCache + ackPath:ackWrite.path + affectedTree:ackWrite.affectedTree + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + newViewCache = [self revertUserWriteOn:oldViewCache + path:ackWrite.path + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeListenComplete) { + newViewCache = [self listenCompleteOldCache:oldViewCache + path:operation.path + writesCache:writesCache + serverCache:optCompleteCache + accumulator:accumulator]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Unknown operation encountered %ld.", (long)operation.type]; + return nil; + } + + NSArray *changes = [self maybeAddValueFromOldViewCache:oldViewCache + newViewCache:newViewCache + changes:accumulator.changes]; + FViewProcessorResult *results = + [[FViewProcessorResult alloc] initWithViewCache:newViewCache + changes:changes]; + return results; +} + +- (NSArray *)maybeAddValueFromOldViewCache:(FViewCache *)oldViewCache + newViewCache:(FViewCache *)newViewCache + changes:(NSArray *)changes { + NSArray *newChanges = changes; + FCacheNode *eventSnap = newViewCache.cachedEventSnap; + if (eventSnap.isFullyInitialized) { + BOOL isLeafOrEmpty = + eventSnap.node.isLeafNode || eventSnap.node.isEmpty; + if ([changes count] > 0 || + !oldViewCache.cachedEventSnap.isFullyInitialized || + (isLeafOrEmpty && + ![eventSnap.node isEqual:oldViewCache.completeEventSnap]) || + ![eventSnap.node.getPriority + isEqual:oldViewCache.completeEventSnap.getPriority]) { + FChange *valueChange = + [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + NSMutableArray *mutableChanges = [changes mutableCopy]; + [mutableChanges addObject:valueChange]; + newChanges = mutableChanges; + } + } + return newChanges; +} + +- (FViewCache *) + generateEventCacheAfterServerEvent:(FViewCache *)viewCache + path:(FPath *)changePath + writesCache:(FWriteTreeRef *)writesCache + source:(id)source + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = viewCache.cachedEventSnap; + if ([writesCache shadowingWriteAtPath:changePath] != nil) { + // we have a shadowing write, ignore changes. + return viewCache; + } else { + FIndexedNode *newEventCache; + if (changePath.isEmpty) { + // TODO: figure out how this plays with "sliding ack windows" + NSAssert( + viewCache.cachedServerSnap.isFullyInitialized, + @"If change path is empty, we must have complete server data"); + id nodeWithLocalWrites; + if (viewCache.cachedServerSnap.isFiltered) { + // We need to special case this, because we need to only apply + // writes to complete children, or we might end up raising + // events for incomplete children. If the server data is + // filtered deep writes cannot be guaranteed to be complete + id serverCache = viewCache.completeServerSnap; + FChildrenNode *completeChildren = + ([serverCache isKindOfClass:[FChildrenNode class]]) + ? serverCache + : [FEmptyNode emptyNode]; + nodeWithLocalWrites = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + completeChildren]; + } else { + nodeWithLocalWrites = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:nodeWithLocalWrites + index:self.filter.index]; + newEventCache = [self.filter + updateFullNode:viewCache.cachedEventSnap.indexedNode + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + NSAssert( + changePath.length == 1, + @"Can't have a priority with additional path components"); + id oldEventNode = oldEventSnap.node; + id serverNode = viewCache.cachedServerSnap.node; + // we might have overwrites for this priority + id updatedPriority = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventNode + existingServerSnap: + serverNode]; + if (updatedPriority != nil) { + newEventCache = + [self.filter updatePriority:updatedPriority + forNode:oldEventSnap.indexedNode]; + } else { + // priority didn't change, keep old node + newEventCache = oldEventSnap.indexedNode; + } + } else { + FPath *childChangePath = [changePath popFront]; + id newEventChild; + if ([oldEventSnap isCompleteForChild:childKey]) { + id serverNode = viewCache.cachedServerSnap.node; + id eventChildUpdate = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventSnap.node + existingServerSnap: + serverNode]; + if (eventChildUpdate != nil) { + newEventChild = + [[oldEventSnap.node getImmediateChild:childKey] + updateChild:childChangePath + withNewChild:eventChildUpdate]; + } else { + // Nothing changed, just keep the old child + newEventChild = + [oldEventSnap.node getImmediateChild:childKey]; + } + } else { + newEventChild = [writesCache + calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + } + if (newEventChild != nil) { + newEventCache = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newEventChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + } else { + // No complete children available or no change + newEventCache = oldEventSnap.indexedNode; + } + } + } + return [viewCache updateEventSnap:newEventCache + isComplete:(oldEventSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)applyServerOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + snap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerSnap = oldViewCache.cachedServerSnap; + FIndexedNode *newServerCache; + id serverFilter = + filterServerNode ? self.filter : self.filter.indexedFilter; + + if (changePath.isEmpty) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:serverFilter.index]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else if (serverFilter.filtersNodes && !oldServerSnap.isFiltered) { + // We want to filter the server node, but we didn't filter the server + // node yet, so simulate a full update + NSAssert(![changePath isEmpty], + @"An empty path should been caught in the other branch"); + NSString *childKey = [changePath getFront]; + FPath *updatePath = [changePath popFront]; + id newChild = [[oldServerSnap.node getImmediateChild:childKey] + updateChild:updatePath + withNewChild:changedSnap]; + FIndexedNode *indexed = + [oldServerSnap.indexedNode updateChild:childKey + withNewChild:newChild]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else { + NSString *childKey = [changePath getFront]; + if (![oldServerSnap isCompleteForPath:changePath] && + changePath.length > 1) { + // We don't update incomplete nodes with updates intended for other + // listeners. + return oldViewCache; + } + FPath *childChangePath = [changePath popFront]; + id childNode = [oldServerSnap.node getImmediateChild:childKey]; + id newChildNode = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + if ([childKey isEqualToString:@".priority"]) { + newServerCache = + [serverFilter updatePriority:newChildNode + forNode:oldServerSnap.indexedNode]; + } else { + newServerCache = + [serverFilter updateChildIn:oldServerSnap.indexedNode + forChildKey:childKey + newChild:newChildNode + affectedPath:childChangePath + fromSource:[FNoCompleteChildSource instance] + accumulator:nil]; + } + } + FViewCache *newViewCache = + [oldViewCache updateServerSnap:newServerCache + isComplete:(oldServerSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:serverFilter.filtersNodes]; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:newViewCache + serverCache:optCompleteCache]; + return [self generateEventCacheAfterServerEvent:newViewCache + path:changePath + writesCache:writesCache + source:source + accumulator:accumulator]; +} + +- (FViewCache *)applyUserOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + changedSnap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = oldViewCache.cachedEventSnap; + FViewCache *newViewCache; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:oldViewCache + serverCache:optCompleteCache]; + if (changePath.isEmpty) { + FIndexedNode *newIndexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:self.filter.index]; + FIndexedNode *newEventCache = + [self.filter updateFullNode:oldEventSnap.indexedNode + withNewNode:newIndexed + accumulator:accumulator]; + newViewCache = [oldViewCache updateEventSnap:newEventCache + isComplete:YES + isFiltered:self.filter.filtersNodes]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + FIndexedNode *newEventCache = [self.filter + updatePriority:changedSnap + forNode:oldViewCache.cachedEventSnap.indexedNode]; + newViewCache = + [oldViewCache updateEventSnap:newEventCache + isComplete:oldEventSnap.isFullyInitialized + isFiltered:oldEventSnap.isFiltered]; + } else { + FPath *childChangePath = [changePath popFront]; + id oldChild = [oldEventSnap.node getImmediateChild:childKey]; + id newChild; + if (childChangePath.isEmpty) { + // Child overwrite, we can replace the child + newChild = changedSnap; + } else { + id childNode = [source completeChild:childKey]; + if (childNode != nil) { + if ([[childChangePath getBack] + isEqualToString:@".priority"] && + [childNode getChild:[childChangePath parent]].isEmpty) { + // This is a priority update on an empty node. If this + // node exists on the server, the server will send down + // the priority in the update, so ignore for now + newChild = childNode; + } else { + newChild = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + } + } else { + newChild = [FEmptyNode emptyNode]; + } + } + if (![oldChild isEqual:newChild]) { + FIndexedNode *newEventSnap = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + newViewCache = [oldViewCache + updateEventSnap:newEventSnap + isComplete:oldEventSnap.isFullyInitialized + isFiltered:self.filter.filtersNodes]; + } else { + newViewCache = oldViewCache; + } + } + } + return newViewCache; +} + ++ (BOOL)cache:(FViewCache *)viewCache hasChild:(NSString *)childKey { + return [viewCache.cachedEventSnap isCompleteForChild:childKey]; +} + +/** + * @param changedChildren NSDictionary of child name (NSString*) to child value + * (id) + */ +- (FViewCache *)applyUserMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + accumulator:(FChildChangeAccumulator *)accumulator { + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if ([FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if (![FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)applyServerMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + // If we don't have a cache yet, this merge was intended for a previously + // listen in the same location. Ignore it and wait for the complete data + // update coming soon. + if (viewCache.cachedServerSnap.node.isEmpty && + !viewCache.cachedServerSnap.isFullyInitialized) { + return viewCache; + } + + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + FCompoundWrite *actualMerge; + if (path.isEmpty) { + actualMerge = changedChildren; + } else { + actualMerge = + [[FCompoundWrite emptyWrite] addCompoundWrite:changedChildren + atPath:path]; + } + id serverNode = viewCache.cachedServerSnap.node; + + NSDictionary *childCompoundWrites = actualMerge.childCompoundWrites; + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + if ([serverNode hasChild:childKey]) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + bool isUnknownDeepMerge = + ![viewCache.cachedServerSnap isCompleteForChild:childKey] && + childMerge.rootWrite == nil; + if (![serverNode hasChild:childKey] && !isUnknownDeepMerge) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)ackUserWriteOn:(FViewCache *)viewCache + ackPath:(FPath *)ackPath + affectedTree:(FImmutableTree *)affectedTree + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + + if ([writesCache shadowingWriteAtPath:ackPath] != nil) { + return viewCache; + } + + // Only filter server node if it is currently filtered + BOOL filterServerNode = viewCache.cachedServerSnap.isFiltered; + + // Essentially we'll just get our existing server cache for the affected + // paths and re-apply it as a server update now that it won't be shadowed. + FCacheNode *serverCache = viewCache.cachedServerSnap; + if (affectedTree.value != nil) { + // This is an overwrite. + if ((ackPath.isEmpty && serverCache.isFullyInitialized) || + [serverCache isCompleteForPath:ackPath]) { + return + [self applyServerOverwriteTo:viewCache + changePath:ackPath + snap:[serverCache.node getChild:ackPath] + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else if (ackPath.isEmpty) { + // This is a goofy edge case where we are acking data at this + // location but don't have full data. We should just re-apply + // whatever we have in our cache as a merge. + FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + for (FNamedNode *child in serverCache.node.childEnumerator) { + changedChildren = [changedChildren addWrite:child.node + atKey:child.name]; + } + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else { + return viewCache; + } + } else { + // This is a merge. + __block FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + [affectedTree forEach:^(FPath *mergePath, id value) { + FPath *serverCachePath = [ackPath child:mergePath]; + if ([serverCache isCompleteForPath:serverCachePath]) { + changedChildren = [changedChildren + addWrite:[serverCache.node getChild:serverCachePath] + atPath:mergePath]; + } + }]; + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } +} + +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + if ([writesCache shadowingWriteAtPath:path] != nil) { + return viewCache; + } else { + id source = [[FWriteTreeCompleteChildSource alloc] + initWithWrites:writesCache + viewCache:viewCache + serverCache:optCompleteCache]; + FIndexedNode *oldEventCache = viewCache.cachedEventSnap.indexedNode; + FIndexedNode *newEventCache; + if (path.isEmpty || [[path getFront] isEqualToString:@".priority"]) { + id newNode; + if (viewCache.cachedServerSnap.isFullyInitialized) { + newNode = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } else { + newNode = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + viewCache.cachedServerSnap.node]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:newNode + index:self.filter.index]; + newEventCache = [self.filter updateFullNode:oldEventCache + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [path getFront]; + id newChild = + [writesCache calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + if (newChild == nil && + [viewCache.cachedServerSnap isCompleteForChild:childKey]) { + newChild = [oldEventCache.node getImmediateChild:childKey]; + } + if (newChild != nil) { + newEventCache = [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:newChild + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else if (newChild == nil && + [viewCache.cachedEventSnap.node hasChild:childKey]) { + // No complete child available, delete the existing one, if any + newEventCache = + [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:[FEmptyNode emptyNode] + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else { + newEventCache = oldEventCache; + } + if (newEventCache.node.isEmpty && + viewCache.cachedServerSnap.isFullyInitialized) { + // We might have reverted all child writes. Maybe the old event + // was a leaf node. + id complete = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + if (complete.isLeafNode) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:complete]; + newEventCache = [self.filter updateFullNode:newEventCache + withNewNode:indexed + accumulator:accumulator]; + } + } + } + BOOL complete = viewCache.cachedServerSnap.isFullyInitialized || + [writesCache shadowingWriteAtPath:[FPath empty]] != nil; + return [viewCache updateEventSnap:newEventCache + isComplete:complete + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)listenCompleteOldCache:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)servercache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerNode = viewCache.cachedServerSnap; + FViewCache *newViewCache = [viewCache + updateServerSnap:oldServerNode.indexedNode + isComplete:(oldServerNode.isFullyInitialized || path.isEmpty) + isFiltered:oldServerNode.isFiltered]; + return [self + generateEventCacheAfterServerEvent:newViewCache + path:path + writesCache:writesCache + source:[FNoCompleteChildSource instance] + accumulator:accumulator]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h new file mode 100644 index 00000000..8d3e2ef6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; + +@interface FViewProcessorResult : NSObject +@property(nonatomic, strong, readonly) FViewCache *viewCache; +/** + * List of FChanges. + */ +@property(nonatomic, strong, readonly) NSArray *changes; + +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m new file mode 100644 index 00000000..0d38947b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessorResult.h" +#import "FViewCache.h" + +@interface FViewProcessorResult () +@property(nonatomic, strong, readwrite) FViewCache *viewCache; +@property(nonatomic, strong, readwrite) NSArray *changes; +@end + +@implementation FViewProcessorResult +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes { + self = [super init]; + if (self) { + self.viewCache = viewCache; + self.changes = changes; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h new file mode 100644 index 00000000..a4f8b156 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FTypedefs.h" +#import "FTypedefs_Private.h" + +@protocol FIRAuthInterop; + +@protocol FAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback; + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener; + +@end + +@interface FAuthTokenProvider : NSObject + ++ (id)authTokenProviderWithAuth:(id)auth; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m new file mode 100644 index 00000000..61bfb033 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m @@ -0,0 +1,121 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Auth/Public/FIRAuthInterop.h" + +#import "FIRDatabaseQuery_Private.h" +#import "FIRNoopAuthTokenProvider.h" +#import "FUtilities.h" + +@interface FAuthStateListenerWrapper : NSObject + +@property(nonatomic, copy) fbt_void_nsstring listener; +@property(nonatomic, weak) id auth; + +@end + +@implementation FAuthStateListenerWrapper + +- (instancetype)initWithListener:(fbt_void_nsstring)listener + auth:(id)auth { + self = [super init]; + if (self != nil) { + self->_listener = listener; + self->_auth = auth; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(authStateDidChangeNotification:) + name:FIRAuthStateDidChangeInternalNotification + object:nil]; + } + return self; +} + +- (void)authStateDidChangeNotification:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + if (notification.object == self.auth) { + NSString *token = + userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + self.listener(token); + }); + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + +@interface FIRFirebaseAuthTokenProvider : NSObject + +@property(nonatomic, strong) id auth; +/** Strong references to the auth listeners as they are only weak in + * FIRFirebaseApp */ +@property(nonatomic, strong) NSMutableArray *authListeners; + +- (instancetype)initWithAuth:(id)auth; + +@end + +@implementation FIRFirebaseAuthTokenProvider + +- (instancetype)initWithAuth:(id)auth { + self = [super init]; + if (self != nil) { + self->_auth = auth; + self->_authListeners = [NSMutableArray array]; + } + return self; +} + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + if (self.auth == nil) { + // Signal that Auth is not available by returning nil. + callback(nil, nil); + } else { + [self.auth getTokenForcingRefresh:forceRefresh + withCallback:^(NSString *_Nullable token, + NSError *_Nullable error) { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(token, error); + }); + }]; + } +} + +- (void)listenForTokenChanges:(_Nonnull fbt_void_nsstring)listener { + FAuthStateListenerWrapper *wrapper = + [[FAuthStateListenerWrapper alloc] initWithListener:listener + auth:self.auth]; + [self.authListeners addObject:wrapper]; +} + +@end + +@implementation FAuthTokenProvider + ++ (id)authTokenProviderWithAuth: + (id)authInterop { + return [[FIRFirebaseAuthTokenProvider alloc] initWithAuth:authInterop]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h new file mode 100644 index 00000000..137c0ce7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import + +@interface FIRNoopAuthTokenProvider : NSObject + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m new file mode 100644 index 00000000..c50d3085 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRNoopAuthTokenProvider.h" +#import "FAuthTokenProvider.h" +#import "FIRDatabaseQuery_Private.h" + +@implementation FIRNoopAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(nil, nil); + }); +} + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener { + // no-op, because token never changes +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h new file mode 100644 index 00000000..6305d34e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FCachePolicy + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries; +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck; +- (float)percentOfQueriesToPruneAtOnce; +- (NSUInteger)maxNumberOfQueriesToKeep; + +@end + +@interface FLRUCachePolicy : NSObject + +@property(nonatomic, readonly) NSUInteger maxSize; + +- (id)initWithMaxSize:(NSUInteger)maxSize; + +@end + +@interface FNoCachePolicy : NSObject + ++ (FNoCachePolicy *)noCachePolicy; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m new file mode 100644 index 00000000..c1ecd98e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCachePolicy.h" + +@interface FLRUCachePolicy () + +@property(nonatomic, readwrite) NSUInteger maxSize; + +@end + +static const NSUInteger kFServerUpdatesBetweenCacheSizeChecks = 1000; +static const NSUInteger kFMaxNumberOfPrunableQueriesToKeep = 1000; +static const float kFPercentOfQueriesToPruneAtOnce = 0.2f; + +@implementation FLRUCachePolicy + +- (id)initWithMaxSize:(NSUInteger)maxSize { + self = [super init]; + if (self != nil) { + self->_maxSize = maxSize; + } + return self; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return cacheSize > self.maxSize || + numTrackedQueries > kFMaxNumberOfPrunableQueriesToKeep; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return serverUpdatesSinceLastCheck > kFServerUpdatesBetweenCacheSizeChecks; +} + +- (float)percentOfQueriesToPruneAtOnce { + return kFPercentOfQueriesToPruneAtOnce; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return kFMaxNumberOfPrunableQueriesToKeep; +} + +@end + +@implementation FNoCachePolicy + ++ (FNoCachePolicy *)noCachePolicy { + return [[FNoCachePolicy alloc] init]; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return NO; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return NO; +} + +- (float)percentOfQueriesToPruneAtOnce { + return 0; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return NSUIntegerMax; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h new file mode 100644 index 00000000..6d32b988 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" +#import "FQuerySpec.h" +#import "FStorageEngine.h" + +@class FCacheNode; +@class FTrackedQuery; +@class FPruneForest; +@class FRepoInfo; + +@interface FLevelDBStorageEngine : NSObject + ++ (NSString *)firebaseDir; + +- (id)initWithPath:(NSString *)path; + +- (void)runLegacyMigration:(FRepoInfo *)info; +- (void)purgeEverything; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m new file mode 100644 index 00000000..eb1fa59e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m @@ -0,0 +1,993 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FLevelDBStorageEngine.h" + +#import "APLevelDB.h" +#import "FEmptyNode.h" +#import "FPendingPut.h" // For legacy migration +#import "FPruneForest.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import "FWriteRecord.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FLevelDBStorageEngine () + +@property(nonatomic, strong) NSString *basePath; +@property(nonatomic, strong) APLevelDB *writesDB; +@property(nonatomic, strong) APLevelDB *serverCacheDB; + +@end + +// WARNING: If you change this, you need to write a migration script +static NSString *const kFPersistenceVersion = @"1"; + +static NSString *const kFServerDBPath = @"server_data"; +static NSString *const kFWritesDBPath = @"writes"; + +static NSString *const kFUserWriteId = @"id"; +static NSString *const kFUserWritePath = @"path"; +static NSString *const kFUserWriteOverwrite = @"o"; +static NSString *const kFUserWriteMerge = @"m"; + +static NSString *const kFTrackedQueryId = @"id"; +static NSString *const kFTrackedQueryPath = @"path"; +static NSString *const kFTrackedQueryParams = @"p"; +static NSString *const kFTrackedQueryLastUse = @"lu"; +static NSString *const kFTrackedQueryIsComplete = @"c"; +static NSString *const kFTrackedQueryIsActive = @"a"; + +static NSString *const kFServerCachePrefix = @"/server_cache/"; +// '~' is the last non-control character in the ASCII table until 127 +// We wan't the entire range of thing stored in the DB +static NSString *const kFServerCacheRangeEnd = @"/server_cache~"; +static NSString *const kFTrackedQueriesPrefix = @"/tracked_queries/"; +static NSString *const kFTrackedQueryKeysPrefix = @"/tracked_query_keys/"; + +// Failed to load JSON because a valid JSON turns out to be NaN while +// deserializing +static const NSInteger kFNanFailureCode = 3840; + +static NSString *writeRecordKey(NSUInteger writeId) { + return [NSString stringWithFormat:@"%lu", (unsigned long)(writeId)]; +} + +static NSString *serverCacheKey(FPath *path) { + return [NSString stringWithFormat:@"%@%@", kFServerCachePrefix, + ([path toStringWithTrailingSlash])]; +} + +static NSString *trackedQueryKey(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu", kFTrackedQueriesPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKeyPrefix(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu/", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKey(NSUInteger trackedQueryId, NSString *key) { + return [NSString stringWithFormat:@"%@%lu/%@", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId, key]; +} + +@implementation FLevelDBStorageEngine +#pragma mark - Constructors + +- (id)initWithPath:(NSString *)dbPath { + self = [super init]; + if (self) { + self.basePath = [[FLevelDBStorageEngine firebaseDir] + stringByAppendingPathComponent:dbPath]; + /* For reference: + serverDataDB = [aPersistence createDbByName:@"server_data"]; + FPangolinDB *completenessDb = [aPersistence + createDbByName:@"server_complete"]; + */ + [FLevelDBStorageEngine ensureDir:self.basePath markAsDoNotBackup:YES]; + [self runMigration]; + [self openDatabases]; + } + return self; +} + +- (void)runMigration { + // Currently we're at version 1, so all we need to do is write that to a + // file + NSString *versionFile = + [self.basePath stringByAppendingPathComponent:@"version"]; + NSError *error; + NSString *oldVersion = + [NSString stringWithContentsOfFile:versionFile + encoding:NSUTF8StringEncoding + error:&error]; + if (!oldVersion) { + // This is probably fine, we don't have a version file yet + BOOL success = [kFPersistenceVersion writeToFile:versionFile + atomically:NO + encoding:NSUTF8StringEncoding + error:&error]; + if (!success) { + FFWarn(@"I-RDB076001", @"Failed to write version for database: %@", + error); + } + } else if ([oldVersion isEqualToString:kFPersistenceVersion]) { + // Everythings fine no need for migration + } else if ([oldVersion length] == 0) { + FFWarn(@"I-RDB076036", + @"Version file empty. Assuming database version 1."); + } else { + // If we add more versions in the future, we need to run migration here + [NSException raise:NSInternalInconsistencyException + format:@"Unrecognized database version: %@", oldVersion]; + } +} + +- (void)runLegacyMigration:(FRepoInfo *)info { + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + NSString *firebaseDir = + [documentsDir stringByAppendingPathComponent:@"firebase"]; + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", info.host, info.namespace]; + NSString *legacyBaseDir = + [NSString stringWithFormat:@"%@/1/%@/v1", firebaseDir, repoHashString]; + if ([[NSFileManager defaultManager] fileExistsAtPath:legacyBaseDir]) { + FFWarn(@"I-RDB076002", @"Legacy database found, migrating..."); + // We only need to migrate writes + NSError *error = nil; + APLevelDB *writes = [APLevelDB + levelDBWithPath:[legacyBaseDir stringByAppendingPathComponent: + @"outstanding_puts"] + error:&error]; + if (writes != nil) { + __block NSUInteger numberOfWritesRestored = 0; + // Maybe we could use write batches, but what the heck, I'm sure + // it'll go fine :P + [writes enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + id pendingPut = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + if ([pendingPut isKindOfClass:[FPendingPut class]]) { + FPendingPut *put = pendingPut; + id newNode = + [FSnapshotUtilities nodeFrom:put.data + priority:put.priority]; + [self saveUserOverwrite:newNode + atPath:put.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut + isKindOfClass:[FPendingPutPriority class]]) { + // This is for backwards compatibility. Older clients will + // save FPendingPutPriority. New ones will need to read it and + // translate. + FPendingPutPriority *putPriority = pendingPut; + FPath *priorityPath = + [putPriority.path childFromString:@".priority"]; + id newNode = + [FSnapshotUtilities nodeFrom:putPriority.priority + priority:nil]; + [self saveUserOverwrite:newNode + atPath:priorityPath + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut isKindOfClass:[FPendingUpdate class]]) { + FPendingUpdate *update = pendingPut; + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:update.data]; + [self saveUserMerge:merge + atPath:update.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else { + FFWarn(@"I-RDB076003", + @"Failed to migrate legacy write, meh!"); + } + }]; + FFWarn(@"I-RDB076004", @"Migrated %lu writes", + (unsigned long)numberOfWritesRestored); + [writes close]; + FFWarn(@"I-RDB076005", @"Deleting legacy database..."); + BOOL success = + [[NSFileManager defaultManager] removeItemAtPath:legacyBaseDir + error:&error]; + if (!success) { + FFWarn(@"I-RDB076006", @"Failed to delete legacy database: %@", + error); + } else { + FFWarn(@"I-RDB076007", @"Finished migrating legacy database."); + } + } else { + FFWarn(@"I-RDB076008", @"Failed to migrate old database: %@", + error); + } + } +} + +- (void)openDatabases { + self.serverCacheDB = [self createDB:kFServerDBPath]; + self.writesDB = [self createDB:kFWritesDBPath]; +} + +- (void)purgeDatabase:(NSString *)dbPath { + NSString *path = [self.basePath stringByAppendingPathComponent:dbPath]; + NSError *error; + FFWarn(@"I-RDB076009", @"Deleting database at path %@", path); + BOOL success = [[NSFileManager defaultManager] removeItemAtPath:path + error:&error]; + if (!success) { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to delete database files: %@", error]; + } +} + +- (void)purgeEverything { + [self close]; + [@[ kFServerDBPath, kFWritesDBPath ] + enumerateObjectsUsingBlock:^(NSString *dbPath, NSUInteger idx, + BOOL *stop) { + [self purgeDatabase:dbPath]; + }]; + + [self openDatabases]; +} + +- (void)close { + // autoreleasepool will cause deallocation which will close the DB + @autoreleasepool { + [self.serverCacheDB close]; + self.serverCacheDB = nil; + [self.writesDB close]; + self.writesDB = nil; + } +} + ++ (NSString *)firebaseDir { +#if TARGET_OS_IOS || TARGET_OS_TV + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + return [documentsDir stringByAppendingPathComponent:@"firebase"]; +#elif TARGET_OS_OSX + return [NSHomeDirectory() stringByAppendingPathComponent:@".firebase"]; +#endif +} + +- (APLevelDB *)createDB:(NSString *)dbName { + NSError *err = nil; + NSString *path = [self.basePath stringByAppendingPathComponent:dbName]; + APLevelDB *db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + FFWarn(@"I-RDB076036", + @"Failed to read database persistence file '%@': %@", dbName, + [err localizedDescription]); + err = nil; + + // Delete the database and try again. + [self purgeDatabase:dbName]; + db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + NSString *reason = [NSString + stringWithFormat:@"Error initializing persistence: %@", + [err description]]; + @throw [NSException + exceptionWithName:@"FirebaseDatabasePersistenceFailure" + reason:reason + userInfo:nil]; + } + } + + return db; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteOverwrite : [node valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user overwrite: %@, (Error: %@)", + write, error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteMerge : [merge valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user merge: %@ (Error: %@)", write, + error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.writesDB removeKey:writeRecordKey(writeId)]; +} + +- (void)removeAllUserWrites { + __block NSUInteger count = 0; + NSDate *start = [NSDate date]; + id batch = [self.writesDB beginWriteBatch]; + [self.writesDB enumerateKeys:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + count++; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076010", @"Failed to remove all users writes on disk!"); + } else { + FFDebug(@"I-RDB076011", @"Removed %lu writes in %fms", + (unsigned long)count, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSArray *)userWrites { + NSDate *date = [NSDate date]; + NSMutableArray *writes = [NSMutableArray array]; + [self.writesDB enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + NSError *error = nil; + NSDictionary *writeJSON = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (writeJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076012", + @"Failed to deserialize write (%@), likely because of out " + @"of range doubles (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076013", @"Removing failed write with key %@", key); + [self.writesDB removeKey:key]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialize write: %@", error]; + } + } else { + NSInteger writeId = + ((NSNumber *)writeJSON[kFUserWriteId]).integerValue; + FPath *path = [FPath pathWithString:writeJSON[kFUserWritePath]]; + FWriteRecord *writeRecord; + if (writeJSON[kFUserWriteMerge] != nil) { + // It's a merge + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:writeJSON[kFUserWriteMerge]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + merge:merge + writeId:writeId]; + } else { + // It's an overwrite + NSAssert(writeJSON[kFUserWriteOverwrite] != nil, + @"Persisted write did not contain merge or overwrite!"); + id node = + [FSnapshotUtilities nodeFrom:writeJSON[kFUserWriteOverwrite]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + overwrite:node + writeId:writeId + visible:YES]; + } + [writes addObject:writeRecord]; + } + }]; + // Make sure writes are sorted + [writes sortUsingComparator:^NSComparisonResult(FWriteRecord *one, + FWriteRecord *two) { + if (one.writeId < two.writeId) { + return NSOrderedAscending; + } else if (one.writeId > two.writeId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + FFDebug(@"I-RDB076014", @"Loaded %lu writes in %fms", + (unsigned long)writes.count, [date timeIntervalSinceNow] * -1000); + return writes; +} + +- (id)serverCacheAtPath:(FPath *)path { + NSDate *start = [NSDate date]; + id data = [self internalNestedDataForPath:path]; + id node = [FSnapshotUtilities nodeFrom:data]; + FFDebug(@"I-RDB076015", @"Loaded node with %d children at %@ in %fms", + [node numChildren], path, [start timeIntervalSinceNow] * -1000); + return node; +} + +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block id node = [FEmptyNode emptyNode]; + [keys enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + id data = [self internalNestedDataForPath:[path childFromString:key]]; + node = [node updateImmediateChild:key + withNewChild:[FSnapshotUtilities nodeFrom:data]]; + }]; + FFDebug(@"I-RDB076016", + @"Loaded node with %d children for %lu keys at %@ in %fms", + [node numChildren], (unsigned long)keys.count, path, + [start timeIntervalSinceNow] * -1000); + return node; +} + +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + __block NSUInteger counter = 0; + if (merge) { + // remove any children that exist + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + FPath *childPath = [path childFromString:childKey]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:childNode + atPath:childPath + batch:batch + counter:&counter]; + }]; + } else { + // remove everything + [self removeAllWithPrefix:serverCacheKey(path) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node atPath:path batch:batch counter:&counter]; + } + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076017", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076018", @"Saved %lu leaf nodes for overwrite in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block NSUInteger counter = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node + atPath:childPath + batch:batch + counter:&counter]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076019", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076020", @"Saved %lu leaf nodes for merge in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveNodeInternal:(id)node + atPath:(FPath *)path + batch:(id)batch + counter:(NSUInteger *)counter { + id data = [node valForExport:YES]; + if (data != nil && ![data isKindOfClass:[NSNull class]]) { + [self internalSetNestedData:data + forKey:serverCacheKey(path) + withBatch:batch + counter:counter]; + } +} + +- (NSUInteger)serverCacheEstimatedSizeInBytes { + // Use the exact size, because for pruning the approximate size can lead to + // weird situations where we prune everything because no compaction is ever + // run + return [self.serverCacheDB exactSizeFrom:kFServerCachePrefix + to:kFServerCacheRangeEnd]; +} + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path { + // TODO: be more intelligent, don't scan entire database... + + __block NSUInteger pruned = 0; + __block NSUInteger kept = 0; + NSDate *start = [NSDate date]; + + NSString *prefix = serverCacheKey(path); + id batch = [self.serverCacheDB beginWriteBatch]; + + [self.serverCacheDB + enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *dbKey, BOOL *stop) { + NSString *pathStr = + [dbKey substringFromIndex:prefix.length]; + FPath *relativePath = [[FPath alloc] initWith:pathStr]; + if ([pruneForest shouldPruneUnkeptDescendantsAtPath: + relativePath]) { + pruned++; + [batch removeKey:dbKey]; + } else { + kept++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076021", @"Failed to prune cache on disk!"); + } else { + FFDebug(@"I-RDB076022", @"Pruned %lu paths, kept %lu paths in %fms", + (unsigned long)pruned, (unsigned long)kept, + [start timeIntervalSinceNow] * -1000); + } +} + +#pragma mark - Tracked Queries + +- (NSArray *)loadTrackedQueries { + NSDate *date = [NSDate date]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + [self.serverCacheDB + enumerateKeysWithPrefix:kFTrackedQueriesPrefix + asData:^(NSString *key, NSData *data, BOOL *stop) { + NSError *error = nil; + NSDictionary *queryJSON = + [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (queryJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn( + @"I-RDB076023", + @"Failed to deserialize tracked query " + @"(%@), likely because of out of range " + @"doubles (Error: %@)", + [[NSString alloc] + initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076024", + @"Removing failed tracked query with " + @"key %@", + key); + [self.serverCacheDB removeKey:key]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Failed to deserialize tracked " + @"query: %@", + error]; + } + } else { + NSUInteger queryId = + ((NSNumber *)queryJSON[kFTrackedQueryId]) + .unsignedIntegerValue; + FPath *path = + [FPath pathWithString: + queryJSON[kFTrackedQueryPath]]; + FQueryParams *params = [FQueryParams + fromQueryObject:queryJSON + [kFTrackedQueryParams]]; + FQuerySpec *query = + [[FQuerySpec alloc] initWithPath:path + params:params]; + BOOL isComplete = + [queryJSON[kFTrackedQueryIsComplete] + boolValue]; + BOOL isActive = + [queryJSON[kFTrackedQueryIsActive] + boolValue]; + NSTimeInterval lastUse = + [queryJSON[kFTrackedQueryLastUse] + doubleValue]; + + FTrackedQuery *trackedQuery = + [[FTrackedQuery alloc] + initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:isComplete]; + + [trackedQueries addObject:trackedQuery]; + } + }]; + FFDebug(@"I-RDB076025", @"Loaded %lu tracked queries in %fms", + (unsigned long)trackedQueries.count, + [date timeIntervalSinceNow] * -1000); + return trackedQueries; +} + +- (void)removeTrackedQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [batch removeKey:trackedQueryKey(queryId)]; + __block NSUInteger keyCount = 0; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + keyCount++; + }]; + + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076026", @"Failed to remove tracked query on disk!"); + } else { + FFDebug(@"I-RDB076027", + @"Removed query with id %lu (and removed %lu keys) in %fms", + (unsigned long)queryId, (unsigned long)keyCount, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveTrackedQuery:(FTrackedQuery *)query { + NSDate *start = [NSDate date]; + NSDictionary *trackedQuery = @{ + kFTrackedQueryId : @(query.queryId), + kFTrackedQueryPath : [query.query.path toStringWithTrailingSlash], + kFTrackedQueryParams : [query.query.params wireProtocolParams], + kFTrackedQueryLastUse : @(query.lastUse), + kFTrackedQueryIsComplete : @(query.isComplete), + kFTrackedQueryIsActive : @(query.isActive) + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:trackedQuery + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize tracked query (Error: %@)", error); + [self.serverCacheDB setData:data forKey:trackedQueryKey(query.queryId)]; + FFDebug(@"I-RDB076028", @"Saved tracked query %lu in %fms", + (unsigned long)query.queryId, [start timeIntervalSinceNow] * -1000); +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + __block NSUInteger removed = 0; + __block NSUInteger added = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + NSMutableSet *seenKeys = [NSMutableSet set]; + // First, delete any keys that might be stored and are not part of the + // current keys + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + if ([keys containsObject:actualKey]) { + // Already in DB + [seenKeys addObject:actualKey]; + } else { + // Not part of set, delete key + [batch removeKey:dbKey]; + removed++; + } + }]; + + // Next add any keys that are missing in the database + [keys enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + if (![seenKeys containsObject:childKey]) { + [batch setString:childKey + forKey:trackedQueryKeysKey(queryId, childKey)]; + added++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076029", @"Failed to set tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076030", + @"Set %lu tracked keys (%lu added, %lu removed) for query %lu " + @"in %fms", + (unsigned long)keys.count, (unsigned long)added, + (unsigned long)removed, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [removed enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:trackedQueryKeysKey(queryId, key)]; + }]; + [added enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch setString:key forKey:trackedQueryKeysKey(queryId, key)]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076031", @"Failed to update tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076032", + @"Added %lu tracked keys, removed %lu for query %lu in %fms", + (unsigned long)added.count, (unsigned long)removed.count, + (unsigned long)queryId, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + NSMutableSet *set = [NSMutableSet set]; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + [set addObject:actualKey]; + }]; + FFDebug(@"I-RDB076033", @"Loaded %lu tracked keys for query %lu in %fms", + (unsigned long)set.count, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + return set; +} + +#pragma mark - Internal methods + +- (void)removeAllLeafNodesOnPath:(FPath *)path + batch:(id)batch { + while (!path.isEmpty) { + [batch removeKey:serverCacheKey(path)]; + path = [path parent]; + } + // Make sure to delete any nodes at the root + [batch removeKey:serverCacheKey([FPath empty])]; +} + +- (void)removeAllWithPrefix:(NSString *)prefix + batch:(id)batch + database:(APLevelDB *)database { + assert(prefix != nil); + + [database enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + }]; +} + +#pragma mark - Internal helper methods + +- (void)internalSetNestedData:(id)value + forKey:(NSString *)key + withBatch:(id)batch + counter:(NSUInteger *)counter { + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id childKey, id obj, + BOOL *stop) { + assert(obj != nil); + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", key, childKey]; + [self internalSetNestedData:obj + forKey:childPath + withBatch:batch + counter:counter]; + }]; + } else { + NSData *data = [self serializePrimitive:value]; + [batch setData:data forKey:key]; + (*counter)++; + } +} + +- (id)internalNestedDataForPath:(FPath *)path { + NSAssert(path != nil, @"Path was nil!"); + + NSString *baseKey = serverCacheKey(path); + + // HACK to make sure iter is freed now to avoid race conditions (if self.db + // is deleted before iter, you get an access violation). + @autoreleasepool { + APLevelDBIterator *iter = + [APLevelDBIterator iteratorWithLevelDB:self.serverCacheDB]; + + [iter seekToKey:baseKey]; + if (iter.key == nil || ![iter.key hasPrefix:baseKey]) { + // No data. + return nil; + } else { + return [self internalNestedDataFromIterator:iter + andKeyPrefix:baseKey]; + } + } +} + +- (id)internalNestedDataFromIterator:(APLevelDBIterator *)iterator + andKeyPrefix:(NSString *)prefix { + NSString *key = iterator.key; + + if ([key isEqualToString:prefix]) { + id result = [self deserializePrimitive:iterator.valueAsData]; + [iterator nextKey]; + return result; + } else { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + while (key != nil && [key hasPrefix:prefix]) { + NSString *relativePath = [key substringFromIndex:prefix.length]; + NSArray *pathPieces = + [relativePath componentsSeparatedByString:@"/"]; + assert(pathPieces.count > 0); + NSString *childName = pathPieces[0]; + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", prefix, childName]; + id childValue = [self internalNestedDataFromIterator:iterator + andKeyPrefix:childPath]; + [dict setValue:childValue forKey:childName]; + + key = iterator.key; + } + return dict; + } +} + +- (NSData *)serializePrimitive:(id)value { + // HACK: The built-in serialization only works on dicts and arrays. So we + // create an array and then strip off the leading / trailing byte (the [ and + // ]). + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:@[ value ] + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize primitive: %@", error); + + return [data subdataWithRange:NSMakeRange(1, data.length - 2)]; +} + +- (id)fixDoubleParsing:(id)value + __attribute__((no_sanitize("float-cast-overflow"))) { + if ([value isKindOfClass:[NSDecimalNumber class]]) { + // In case the value is an NSDecimalNumber, we may be dealing with + // precisions that are higher than what can be represented in a double. + // In this case it does not suffice to check for integral numbers by + // casting the [value doubleValue] to an int64_t, because this will + // cause the compared values to be rounded to double precision. + // Coupled with a bug in [NSDecimalNumber longLongValue] that triggers + // when converting values with high precision, this would cause + // values of high precision, but with an integral 'doubleValue' + // representation to be converted to bogus values. + // A radar for the NSDecimalNumber issue can be found here: + // http://www.openradar.me/radar?id=5007005597040640 + // Consider the NSDecimalNumber value: 999.9999999999999487 + // This number has a 'doubleValue' of 1000. Using the previous version + // of this method would cause the value to be interpreted to be integral + // and then the resulting value would be based on the longLongValue + // which due to the NSDecimalNumber issue would turn out as -844. + // By using NSDecimal logic to test for integral values, + // 999.9999999999999487 will not be considered integral, and instead + // of triggering the 'longLongValue' issue, it will be returned as + // the 'doubleValue' representation (1000). + // Please note, that even without the NSDecimalNumber issue, the + // 'correct' longLongValue of 999.9999999999999487 is 999 and not 1000, + // so the previous code would cause issues even without the bug + // referenced in the radar. + NSDecimal original = [(NSDecimalNumber *)value decimalValue]; + NSDecimal rounded; + NSDecimalRound(&rounded, &original, 0, NSRoundPlain); + if (NSDecimalCompare(&original, &rounded) != NSOrderedSame) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } else if ([value isKindOfClass:[NSNumber class]]) { + // The parser for double values in JSONSerialization at the root takes + // some short-cuts and delivers wrong results (wrong rounding) for some + // double values, including 2.47. Because we use the exact bytes for + // hashing on the server this will lead to hash mismatches. The parser + // of NSNumber seems to be more in line with what the server expects, so + // we use that here + CFNumberType type = CFNumberGetType((CFNumberRef)value); + if (type == kCFNumberDoubleType || type == kCFNumberFloatType) { + // The NSJSON parser returns all numbers as double values, even + // those that contain no exponent. To make sure that the String + // conversion below doesn't unexpectedly reduce precision, we make + // sure that our number is indeed not an integer. + if ((double)(int64_t)[value doubleValue] != [value doubleValue]) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } + } + return value; +} + +- (id)deserializePrimitive:(NSData *)data { + NSError *error = nil; + id result = + [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingAllowFragments + error:&error]; + if (result != nil) { + return [self fixDoubleParsing:result]; + } else { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076034", + @"Failed to load primitive %@, likely because doubles where " + @"out of range (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + return [NSNull null]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialiaze primitive: %@", error]; + return nil; + } + } +} + ++ (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup { + NSError *error; + BOOL success = + [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + @throw [NSException + exceptionWithName:@"FailedToCreatePersistenceDir" + reason:@"Failed to create persistence directory." + userInfo:@{@"path" : path}]; + } + + if (markAsDoNotBackup) { + NSURL *firebaseDirURL = [NSURL fileURLWithPath:path]; + success = [firebaseDirURL setResourceValue:@YES + forKey:NSURLIsExcludedFromBackupKey + error:&error]; + if (!success) { + FFWarn( + @"I-RDB076035", + @"Failed to mark firebase database folder as do not backup: %@", + error); + [NSException raise:@"Error marking as do not backup" + format:@"Failed to mark folder %@ as do not backup", + firebaseDirURL]; + } + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h new file mode 100644 index 00000000..602bf8cc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +// These are all legacy classes and are used to migrate older persistence data +// base to newer ones These classes should not be used in newer code + +@interface FPendingPut : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id data; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end + +@interface FPendingPutPriority : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; + +@end + +@interface FPendingUpdate : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) NSDictionary *data; + +- (id)initWithPath:(FPath *)aPath andData:(NSDictionary *)aData; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m new file mode 100644 index 00000000..c5195995 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPendingPut.h" + +@implementation FPendingPut + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingPutPriority + +@synthesize path; +@synthesize priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingUpdate + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h new file mode 100644 index 00000000..681c56d5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCacheNode.h" +#import "FCachePolicy.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FQuerySpec.h" +#import "FRepoInfo.h" +#import "FStorageEngine.h" + +@interface FPersistenceManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy; +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path; +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path; + +- (void)setQueryComplete:(FQuerySpec *)spec; +- (void)setQueryActive:(FQuerySpec *)spec; +- (void)setQueryInactive:(FQuerySpec *)spec; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m new file mode 100644 index 00000000..4090da95 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m @@ -0,0 +1,231 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPersistenceManager.h" +#import "FCacheNode.h" +#import "FClock.h" +#import "FIndexedNode.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FTrackedQueryManager.h" +#import "FUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FPersistenceManager () + +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id cachePolicy; +@property(nonatomic, strong) FTrackedQueryManager *trackedQueryManager; +@property(nonatomic) NSUInteger serverCacheUpdatesSinceLastPruneCheck; + +@end + +@implementation FPersistenceManager + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_cachePolicy = cachePolicy; + self->_trackedQueryManager = [[FTrackedQueryManager alloc] + initWithStorageEngine:self.storageEngine + clock:[FSystemClock clock]]; + } + return self; +} + +- (void)close { + [self.storageEngine close]; + self.storageEngine = nil; + self.trackedQueryManager = nil; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserOverwrite:node atPath:path writeId:writeId]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserMerge:merge atPath:path writeId:writeId]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.storageEngine removeUserWrite:writeId]; +} + +- (void)removeAllUserWrites { + [self.storageEngine removeAllUserWrites]; +} + +- (NSArray *)userWrites { + return [self.storageEngine userWrites]; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + NSSet *trackedKeys; + BOOL complete; + // TODO[offline]: Should we use trackedKeys to find out if this location is + // a child of a complete query? + if ([self.trackedQueryManager isQueryComplete:query]) { + complete = YES; + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + if (!query.loadsAllData && trackedQuery.isComplete) { + trackedKeys = [self.storageEngine + trackedQueryKeysForQuery:trackedQuery.queryId]; + } else { + trackedKeys = nil; + } + } else { + complete = NO; + trackedKeys = + [self.trackedQueryManager knownCompleteChildrenAtPath:query.path]; + } + + id node; + if (trackedKeys != nil) { + node = [self.storageEngine serverCacheForKeys:trackedKeys + atPath:query.path]; + } else { + node = [self.storageEngine serverCacheAtPath:query.path]; + } + + FIndexedNode *indexedNode = [FIndexedNode indexedNodeWithNode:node + index:query.index]; + return [[FCacheNode alloc] initWithIndexedNode:indexedNode + isFullyInitialized:complete + isFiltered:(trackedKeys != nil)]; +} + +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)query { + BOOL merge = !query.loadsAllData; + [self.storageEngine updateServerCache:node atPath:query.path merge:merge]; + [self setQueryComplete:query]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + [self.storageEngine updateServerCacheWithMerge:merge atPath:path]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path { + // TODO[offline]: rework this to be more efficient + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + [self applyUserWrite:node toServerCacheAtPath:[path child:relativePath]]; + }]; +} + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path { + // This is a hack to guess whether we already cached this because we got a + // server data update for this write via an existing active default query. + // If we didn't, then we'll manually cache this and add a tracked query to + // mark it complete and keep it cached. Unfortunately this is just a guess + // and it's possible that we *did* get an update (e.g. via a filtered query) + // and by overwriting the cache here, we'll actually store an incorrect + // value (e.g. in the case that we wrote a ServerValue.TIMESTAMP and the + // server resolved it to a different value). + // TODO[offline]: Consider reworking. + if (![self.trackedQueryManager hasActiveDefaultQueryAtPath:path]) { + [self.storageEngine updateServerCache:write atPath:path merge:NO]; + [self.trackedQueryManager ensureCompleteTrackedQueryAtPath:path]; + } +} + +- (void)setQueryComplete:(FQuerySpec *)query { + if (query.loadsAllData) { + [self.trackedQueryManager setQueriesCompleteAtPath:query.path]; + } else { + [self.trackedQueryManager setQueryComplete:query]; + } +} + +- (void)setQueryActive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryActive:spec]; +} + +- (void)setQueryInactive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryInactive:spec]; +} + +- (void)doPruneCheckAfterServerUpdate { + self.serverCacheUpdatesSinceLastPruneCheck++; + if ([self.cachePolicy + shouldCheckCacheSize:self.serverCacheUpdatesSinceLastPruneCheck]) { + FFDebug(@"I-RDB078001", @"Reached prune check threshold. Checking..."); + NSDate *date = [NSDate date]; + self.serverCacheUpdatesSinceLastPruneCheck = 0; + BOOL canPrune = YES; + NSUInteger cacheSize = + [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078002", @"Server cache size: %lu", + (unsigned long)cacheSize); + while (canPrune && + [self.cachePolicy + shouldPruneCacheWithSize:cacheSize + numberOfTrackedQueries:self.trackedQueryManager + .numberOfPrunableQueries]) { + FPruneForest *pruneForest = + [self.trackedQueryManager pruneOldQueries:self.cachePolicy]; + if (pruneForest.prunesAnything) { + [self.storageEngine pruneCache:pruneForest + atPath:[FPath empty]]; + } else { + canPrune = NO; + } + cacheSize = [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078003", @"Cache size after pruning: %lu", + (unsigned long)cacheSize); + } + FFDebug(@"I-RDB078004", @"Pruning round took %fms", + [date timeIntervalSinceNow] * -1000); + } +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine setTrackedQueryKeys:keys + forQueryId:trackedQuery.queryId]; +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQueryId:trackedQuery.queryId]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h new file mode 100644 index 00000000..9e77217a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FPruneForest : NSObject + ++ (FPruneForest *)empty; + +- (BOOL)prunesAnything; +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path; +- (BOOL)shouldKeepPath:(FPath *)path; +- (BOOL)affectsPath:(FPath *)path; +- (FPruneForest *)child:(NSString *)childKey; +- (FPruneForest *)childAtPath:(FPath *)childKey; +- (FPruneForest *)prunePath:(FPath *)path; +- (FPruneForest *)keepPath:(FPath *)path; +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path; +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path; + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *path))block; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m new file mode 100644 index 00000000..e795c693 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m @@ -0,0 +1,194 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPruneForest.h" + +#import "FImmutableTree.h" + +@interface FPruneForest () + +@property(nonatomic, strong) FImmutableTree *pruneForest; + +@end + +@implementation FPruneForest + +static BOOL (^kFPrunePredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return [pruneValue boolValue]; +}; + +static BOOL (^kFKeepPredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return ![pruneValue boolValue]; +}; + ++ (FImmutableTree *)pruneTree { + static dispatch_once_t onceToken; + static FImmutableTree *pruneTree; + dispatch_once(&onceToken, ^{ + pruneTree = [[FImmutableTree alloc] initWithValue:@YES]; + }); + return pruneTree; +} + ++ (FImmutableTree *)keepTree { + static dispatch_once_t onceToken; + static FImmutableTree *keepTree; + dispatch_once(&onceToken, ^{ + keepTree = [[FImmutableTree alloc] initWithValue:@NO]; + }); + return keepTree; +} + +- (id)initWithForest:(FImmutableTree *)tree { + self = [super init]; + if (self != nil) { + self->_pruneForest = tree; + } + return self; +} + ++ (FPruneForest *)empty { + static dispatch_once_t onceToken; + static FPruneForest *forest; + dispatch_once(&onceToken, ^{ + forest = [[FPruneForest alloc] initWithForest:[FImmutableTree empty]]; + }); + return forest; +} + +- (BOOL)prunesAnything { + return [self.pruneForest containsValueMatching:kFPrunePredicate]; +} + +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && [shouldPrune boolValue]; +} + +- (BOOL)shouldKeepPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && ![shouldPrune boolValue]; +} + +- (BOOL)affectsPath:(FPath *)path { + return [self.pruneForest rootMostValueOnPath:path] != nil || + ![[self.pruneForest subtreeAtPath:path] isEmpty]; +} + +- (FPruneForest *)child:(NSString *)childKey { + FImmutableTree *childPruneForest = [self.pruneForest.children get:childKey]; + if (childPruneForest == nil) { + if (self.pruneForest.value != nil) { + childPruneForest = [self.pruneForest.value boolValue] + ? [FPruneForest pruneTree] + : [FPruneForest keepTree]; + } else { + childPruneForest = [FImmutableTree empty]; + } + } else { + if (childPruneForest.value == nil && self.pruneForest.value != nil) { + childPruneForest = [childPruneForest setValue:self.pruneForest.value + atPath:[FPath empty]]; + } + } + return [[FPruneForest alloc] initWithForest:childPruneForest]; +} + +- (FPruneForest *)childAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + return [[self child:path.getFront] childAtPath:[path popFront]]; + } +} + +- (FPruneForest *)prunePath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest pruneTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest keepTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + return [self setPruneValue:[FPruneForest keepTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + return [self setPruneValue:[FPruneForest pruneTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)setPruneValue:(FImmutableTree *)pruneValue + forAll:(NSSet *)children + atPath:(FPath *)path { + FImmutableTree *subtree = [self.pruneForest subtreeAtPath:path]; + __block FImmutableSortedDictionary *childrenDictionary = subtree.children; + [children enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + childrenDictionary = [childrenDictionary insertKey:childKey + withValue:pruneValue]; + }]; + FImmutableTree *newSubtree = + [[FImmutableTree alloc] initWithValue:subtree.value + children:childrenDictionary]; + return [[FPruneForest alloc] + initWithForest:[self.pruneForest setTree:newSubtree atPath:path]]; +} + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *))block { + [self.pruneForest forEach:^(FPath *path, id value) { + if (value != nil && ![value boolValue]) { + block(path); + } + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h new file mode 100644 index 00000000..5f418b80 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FPruneForest; +@class FPath; +@class FCompoundWrite; +@class FQuerySpec; +@class FTrackedQuery; + +@protocol FStorageEngine + +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (id)serverCacheAtPath:(FPath *)path; +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path; +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; +- (NSUInteger)serverCacheEstimatedSizeInBytes; + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path; + +- (NSArray *)loadTrackedQueries; +- (void)removeTrackedQuery:(NSUInteger)queryId; +- (void)saveTrackedQuery:(FTrackedQuery *)query; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId; +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h new file mode 100644 index 00000000..7413816b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; + +@interface FTrackedQuery : NSObject + +@property(nonatomic, readonly) NSUInteger queryId; +@property(nonatomic, strong, readonly) FQuerySpec *query; +@property(nonatomic, readonly) NSTimeInterval lastUse; +@property(nonatomic, readonly) BOOL isComplete; +@property(nonatomic, readonly) BOOL isActive; + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive; +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete; + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse; +- (FTrackedQuery *)setComplete; +- (FTrackedQuery *)setActiveState:(BOOL)isActive; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m new file mode 100644 index 00000000..6ca7ec06 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQuery.h" + +#import "FQuerySpec.h" + +@interface FTrackedQuery () + +@property(nonatomic, readwrite) NSUInteger queryId; +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, readwrite) NSTimeInterval lastUse; +@property(nonatomic, readwrite) BOOL isComplete; +@property(nonatomic, readwrite) BOOL isActive; + +@end + +@implementation FTrackedQuery + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete { + self = [super init]; + if (self != nil) { + self->_queryId = queryId; + self->_query = query; + self->_lastUse = lastUse; + self->_isComplete = isComplete; + self->_isActive = isActive; + } + return self; +} + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive { + return [self initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:NO]; +} + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:lastUse + isActive:self.isActive + isComplete:self.isComplete]; +} + +- (FTrackedQuery *)setComplete { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:self.isActive + isComplete:YES]; +} + +- (FTrackedQuery *)setActiveState:(BOOL)isActive { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:isActive + isComplete:self.isComplete]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FTrackedQuery class]]) { + return NO; + } + FTrackedQuery *other = (FTrackedQuery *)object; + if (self.queryId != other.queryId) + return NO; + if (self.query != other.query && ![self.query isEqual:other.query]) + return NO; + if (self.lastUse != other.lastUse) + return NO; + if (self.isComplete != other.isComplete) + return NO; + if (self.isActive != other.isActive) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self.queryId; + hash = hash * 31 + self.query.hash; + hash = hash * 31 + (self.isActive ? 1 : 0); + hash = hash * 31 + (NSUInteger)self.lastUse; + hash = hash * 31 + (self.isComplete ? 1 : 0); + hash = hash * 31 + (self.isActive ? 1 : 0); + return hash; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h new file mode 100644 index 00000000..cd7d5a18 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FStorageEngine; +@protocol FClock; +@protocol FCachePolicy; +@class FQuerySpec; +@class FPath; +@class FTrackedQuery; +@class FPruneForest; + +@interface FTrackedQueryManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock; + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query; + +- (BOOL)isQueryComplete:(FQuerySpec *)query; + +- (void)removeTrackedQuery:(FQuerySpec *)query; +- (void)setQueryComplete:(FQuerySpec *)query; +- (void)setQueriesCompleteAtPath:(FPath *)path; +- (void)setQueryActive:(FQuerySpec *)query; +- (void)setQueryInactive:(FQuerySpec *)query; + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path; +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path; + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy; +- (NSUInteger)numberOfPrunableQueries; +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path; + +// For testing +- (void)verifyCache; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m new file mode 100644 index 00000000..f0a18e79 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m @@ -0,0 +1,375 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQueryManager.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FImmutableTree.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +@interface FTrackedQueryManager () + +@property(nonatomic, strong) FImmutableTree *trackedQueryTree; +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id clock; +@property(nonatomic) NSUInteger currentQueryId; + +@end + +@implementation FTrackedQueryManager + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_clock = clock; + self->_trackedQueryTree = [FImmutableTree empty]; + + NSTimeInterval lastUse = [clock currentTime]; + + NSArray *trackedQueries = [self.storageEngine loadTrackedQueries]; + [trackedQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *trackedQuery, NSUInteger idx, + BOOL *stop) { + self.currentQueryId = + MAX(trackedQuery.queryId + 1, self.currentQueryId); + if (trackedQuery.isActive) { + trackedQuery = + [[trackedQuery setActiveState:NO] updateLastUse:lastUse]; + FFDebug( + @"I-RDB081001", + @"Setting active query %lu from previous app start inactive", + (unsigned long)trackedQuery.queryId); + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + [self cacheTrackedQuery:trackedQuery]; + }]; + } + return self; +} + ++ (void)assertValidTrackedQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData || query.isDefault, + @"Can't have tracked non-default query that loads all data"); +} + ++ (FQuerySpec *)normalizeQuery:(FQuerySpec *)query { + return query.loadsAllData ? [FQuerySpec defaultQueryAtPath:query.path] + : query; +} + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + NSDictionary *set = [self.trackedQueryTree valueAtPath:query.path]; + return set[query.params]; +} + +- (void)removeTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + NSAssert(trackedQuery, @"Tracked query must exist to be removed!"); + + [self.storageEngine removeTrackedQuery:trackedQuery.queryId]; + NSMutableDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + [trackedQueries removeObjectForKey:query.params]; +} + +- (void)setQueryActive:(FQuerySpec *)query { + [self setQueryActive:YES forQuery:query]; +} + +- (void)setQueryInactive:(FQuerySpec *)query { + [self setQueryActive:NO forQuery:query]; +} + +- (void)setQueryActive:(BOOL)isActive forQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + + // Regardless of whether it's now active or no langer active, we update the + // lastUse time + NSTimeInterval lastUse = [self.clock currentTime]; + if (trackedQuery != nil) { + trackedQuery = + [[trackedQuery updateLastUse:lastUse] setActiveState:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } else { + NSAssert(isActive, @"If we're setting the query to inactive, we should " + @"already be tracking it!"); + trackedQuery = [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:lastUse + isActive:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + + [self cacheTrackedQuery:trackedQuery]; +} + +- (void)setQueryComplete:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (!trackedQuery) { + // We might have removed a query and pruned it before we got the + // complete message from the server... + FFWarn(@"I-RDB081002", + @"Trying to set a query complete that is not tracked!"); + } else if (!trackedQuery.isComplete) { + trackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } else { + // Nothing to do, already marked complete + } +} + +- (void)setQueriesCompleteAtPath:(FPath *)path { + [[self.trackedQueryTree subtreeAtPath:path] + forEach:^(FPath *childPath, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *parms, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isComplete) { + FTrackedQuery *newTrackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:newTrackedQuery]; + [self cacheTrackedQuery:newTrackedQuery]; + } + }]; + }]; +} + +- (BOOL)isQueryComplete:(FQuerySpec *)query { + if ([self isIncludedInDefaultCompleteQuery:query]) { + return YES; + } else if (query.loadsAllData) { + // We didn't find a default complete query, so must not be complete. + return NO; + } else { + NSDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + return [trackedQueries[query.params] isComplete]; + } +} + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path { + return [self.trackedQueryTree + rootMostValueOnPath:path + matching:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isActive]; + }] != nil; +} + +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path { + FQuerySpec *query = [FQuerySpec defaultQueryAtPath:path]; + if (![self isIncludedInDefaultCompleteQuery:query]) { + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (trackedQuery == nil) { + trackedQuery = + [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:[self.clock currentTime] + isActive:NO + isComplete:YES]; + } else { + NSAssert(!trackedQuery.isComplete, + @"This should have been handled above!"); + trackedQuery = [trackedQuery setComplete]; + } + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } +} + +- (BOOL)isIncludedInDefaultCompleteQuery:(FQuerySpec *)query { + return + [self.trackedQueryTree + findRootMostMatchingPath:query.path + predicate:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isComplete]; + }] != nil; +} + +- (void)cacheTrackedQuery:(FTrackedQuery *)query { + [FTrackedQueryManager assertValidTrackedQuery:query.query]; + NSMutableDictionary *trackedDict = + [self.trackedQueryTree valueAtPath:query.query.path]; + if (trackedDict == nil) { + trackedDict = [NSMutableDictionary dictionary]; + self.trackedQueryTree = + [self.trackedQueryTree setValue:trackedDict + atPath:query.query.path]; + } + trackedDict[query.query.params] = query; +} + +- (NSUInteger)numberOfQueriesToPrune:(id)cachePolicy + prunableCount:(NSUInteger)numPrunable { + NSUInteger numPercent = (NSUInteger)ceilf( + numPrunable * [cachePolicy percentOfQueriesToPruneAtOnce]); + NSUInteger maxToKeep = [cachePolicy maxNumberOfQueriesToKeep]; + NSUInteger numMax = (numPrunable > maxToKeep) ? numPrunable - maxToKeep : 0; + // Make sure we get below number of max queries to prune + return MAX(numMax, numPercent); +} + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy { + NSMutableArray *pruneableQueries = [NSMutableArray array]; + NSMutableArray *unpruneableQueries = [NSMutableArray array]; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + [pruneableQueries addObject:trackedQuery]; + } else { + [unpruneableQueries addObject:trackedQuery]; + } + }]; + }]; + [pruneableQueries sortUsingComparator:^NSComparisonResult( + FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.lastUse < q2.lastUse) { + return NSOrderedAscending; + } else if (q1.lastUse > q2.lastUse) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + + __block FPruneForest *pruneForest = [FPruneForest empty]; + NSUInteger numToPrune = + [self numberOfQueriesToPrune:cachePolicy + prunableCount:pruneableQueries.count]; + + // TODO: do in transaction + for (NSUInteger i = 0; i < numToPrune; i++) { + FTrackedQuery *toPrune = pruneableQueries[i]; + pruneForest = [pruneForest prunePath:toPrune.query.path]; + [self removeTrackedQuery:toPrune.query]; + } + + // Keep the rest of the prunable queries + for (NSUInteger i = numToPrune; i < pruneableQueries.count; i++) { + FTrackedQuery *toKeep = pruneableQueries[i]; + pruneForest = [pruneForest keepPath:toKeep.query.path]; + } + + // Also keep unprunable queries + [unpruneableQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *toKeep, NSUInteger idx, BOOL *stop) { + pruneForest = [pruneForest keepPath:toKeep.query.path]; + }]; + + return pruneForest; +} + +- (NSUInteger)numberOfPrunableQueries { + __block NSUInteger count = 0; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + count++; + } + }]; + }]; + return count; +} + +- (NSSet *)filteredQueryIdsAtPath:(FPath *)path { + NSDictionary *queries = [self.trackedQueryTree valueAtPath:path]; + if (queries) { + NSMutableSet *ids = [NSMutableSet set]; + [queries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *query, BOOL *stop) { + if (!query.query.loadsAllData) { + [ids addObject:@(query.queryId)]; + } + }]; + return ids; + } else { + return [NSSet set]; + } +} + +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path { + NSAssert(![self isQueryComplete:[FQuerySpec defaultQueryAtPath:path]], + @"Path is fully complete"); + + NSMutableSet *completeChildren = [NSMutableSet set]; + // First, get complete children from any queries at this location. + NSSet *queryIds = [self filteredQueryIdsAtPath:path]; + [queryIds enumerateObjectsUsingBlock:^(NSNumber *queryId, BOOL *stop) { + NSSet *keys = [self.storageEngine + trackedQueryKeysForQuery:[queryId unsignedIntegerValue]]; + [completeChildren unionSet:keys]; + }]; + + // Second, get any complete default queries immediately below us. + [[[self.trackedQueryTree subtreeAtPath:path] children] + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childTree.value[[FQueryParams defaultInstance]] isComplete]) { + [completeChildren addObject:childKey]; + } + }]; + + return completeChildren; +} + +- (void)verifyCache { + NSArray *storedTrackedQueries = [self.storageEngine loadTrackedQueries]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + + [self.trackedQueryTree forEach:^(FPath *path, NSDictionary *queryDict) { + [trackedQueries addObjectsFromArray:queryDict.allValues]; + }]; + NSComparator comparator = + ^NSComparisonResult(FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.queryId < q2.queryId) { + return NSOrderedAscending; + } else if (q1.queryId > q2.queryId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }; + [trackedQueries sortUsingComparator:comparator]; + storedTrackedQueries = + [storedTrackedQueries sortedArrayUsingComparator:comparator]; + + if (![trackedQueries isEqualToArray:storedTrackedQueries]) { + [NSException + raise:NSInternalInconsistencyException + format:@"Tracked queries and queries stored on disk don't match"]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h new file mode 100644 index 00000000..3aecd818 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FIRDataEventType_h +#define Firebase_FIRDataEventType_h + +#import + +/** + * This enum is the set of events that you can observe at a Firebase Database + * location. + */ +typedef NS_ENUM(NSInteger, FIRDataEventType) { + /// A new child node is added to a location. + FIRDataEventTypeChildAdded, + /// A child node is removed from a location. + FIRDataEventTypeChildRemoved, + /// A child node at a location changes. + FIRDataEventTypeChildChanged, + /// A child node moves relative to the other child nodes at a location. + FIRDataEventTypeChildMoved, + /// Any data changes at a location or, recursively, at any child node. + FIRDataEventTypeValue +} NS_SWIFT_NAME(DataEventType); + +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h new file mode 100644 index 00000000..e88febb6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h @@ -0,0 +1,142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabaseReference; + +/** + * A FIRDataSnapshot contains data from a Firebase Database location. Any time + * you read Firebase data, you receive the data as a FIRDataSnapshot. + * + * FIRDataSnapshots are passed to the blocks you attach with + * observeEventType:withBlock: or observeSingleEvent:withBlock:. They are + * efficiently-generated immutable copies of the data at a Firebase Database + * location. They can't be modified and will never change. To modify data at a + * location, use a FIRDatabaseReference (e.g. with setValue:). + */ +NS_SWIFT_NAME(DataSnapshot) +@interface FIRDataSnapshot : NSObject + +#pragma mark - Navigating and inspecting a snapshot + +/** + * Gets a FIRDataSnapshot for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') + * or a deeper slash-separated path (e.g. 'fred/name/first'). If the child + * location has no data, an empty FIRDataSnapshot is returned. + * + * @param childPathString A relative path to the location of child data. + * @return The FIRDataSnapshot for the child location. + */ +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString; + +/** + * Return YES if the specified child exists. + * + * @param childPathString A relative path to the location of a potential child. + * @return YES if data exists at the specified childPathString, else NO. + */ +- (BOOL)hasChild:(NSString *)childPathString; + +/** + * Return YES if the DataSnapshot has any children. + * + * @return YES if this snapshot has any children, else NO. + */ +- (BOOL)hasChildren; + +/** + * Return YES if the DataSnapshot contains a non-null value. + * + * @return YES if this snapshot contains a non-null value, else NO. + */ +- (BOOL)exists; + +#pragma mark - Data export + +/** + * Returns the raw value at this location, coupled with any metadata, such as + * priority. + * + * Priorities, where they exist, are accessible under the ".priority" key in + * instances of NSDictionary. For leaf locations with priorities, the value will + * be under the ".value" key. + */ +- (id __nullable)valueInExportFormat; + +#pragma mark - Properties + +/** + * Returns the contents of this data snapshot as native types. + * + * Data types returned: + * + NSDictionary + * + NSArray + * + NSNumber (also includes booleans) + * + NSString + * + * @return The data as a native object. + */ +@property(strong, readonly, nonatomic, nullable) id value; + +/** + * Gets the number of children for this DataSnapshot. + * + * @return An integer indicating the number of children. + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Gets a FIRDatabaseReference for the location that this data came from. + * + * @return A FIRDatabaseReference instance for the location of this data. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +/** + * The key of the location that generated this FIRDataSnapshot. + * + * @return An NSString containing the key for the location of this + * FIRDataSnapshot. + */ +@property(strong, readonly, nonatomic) NSString *key; + +/** + * An iterator for snapshots of the child nodes in this snapshot. + * You can use the native for..in syntax: + * + * for (FIRDataSnapshot* child in snapshot.children) { + * ... + * } + * + * @return An NSEnumerator of the children. + */ +@property(strong, readonly, nonatomic) + NSEnumerator *children; + +/** + * The priority of the data in this FIRDataSnapshot. + * + * @return The priority as a string, or nil if no priority was set. + */ +@property(strong, readonly, nonatomic, nullable) id priority; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h new file mode 100644 index 00000000..02af8c77 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h @@ -0,0 +1,182 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The entry point for accessing a Firebase Database. You can get an instance + * by calling [FIRDatabase database]. To access a location in the database and + * read or write data, use [FIRDatabase reference]. + */ +NS_SWIFT_NAME(Database) +@interface FIRDatabase : NSObject + +/** + * The NSObject initializer that has been marked as unavailable. Use the + * `database` method instead + * + * @return An instancetype instance + */ +- (instancetype)init + __attribute__((unavailable("use the database method instead"))); + +/** + * Gets the instance of FIRDatabase for the default FIRApp. + * + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)database NS_SWIFT_NAME(database()); + +/** + * Gets a FirebaseDatabase instance for the specified URL. + * + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseWithURL:(NSString *)url NS_SWIFT_NAME(database(url:)); + +/** + * Gets a FirebaseDatabase instance for the specified URL, using the specified + * FirebaseApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ +// clang-format off ++ (FIRDatabase *)databaseForApp:(FIRApp *)app + URL:(NSString *)url NS_SWIFT_NAME(database(app:url:)); +// clang-format on + +/** + * Gets an instance of FIRDatabase for a specific FIRApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseForApp:(FIRApp *)app NS_SWIFT_NAME(database(app:)); + +/** The FIRApp instance to which this FIRDatabase belongs. */ +@property(weak, readonly, nonatomic) FIRApp *app; + +/** + * Gets a FIRDatabaseReference for the root of your Firebase Database. + */ +- (FIRDatabaseReference *)reference; + +/** + * Gets a FIRDatabaseReference for the provided path. + * + * @param path Path to a location in your Firebase Database. + * @return A FIRDatabaseReference pointing to the specified path. + */ +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path; + +/** + * Gets a FIRDatabaseReference for the provided URL. The URL must be a URL to a + * path within this Firebase Database. To create a FIRDatabaseReference to a + * different database, create a FIRApp} with a FIROptions object configured with + * the appropriate database URL. + * + * @param databaseUrl A URL to a path within your database. + * @return A FIRDatabaseReference for the provided URL. + */ +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl; + +/** + * The Firebase Database client automatically queues writes and sends them to + * the server at the earliest opportunity, depending on network connectivity. In + * some cases (e.g. offline usage) there may be a large number of writes waiting + * to be sent. Calling this method will purge all outstanding writes so they are + * abandoned. + * + * All writes will be purged, including transactions and onDisconnect writes. + * The writes will be rolled back locally, perhaps triggering events for + * affected event listeners, and the client will not (re-)send them to the + * Firebase Database backend. + */ +- (void)purgeOutstandingWrites; + +/** + * Shuts down our connection to the Firebase Database backend until goOnline is + * called. + */ +- (void)goOffline; + +/** + * Resumes our connection to the Firebase Database backend after a previous + * goOffline call. + */ +- (void)goOnline; + +/** + * The Firebase Database client will cache synchronized data and keep track of + * all writes you've initiated while your application is running. It seamlessly + * handles intermittent network connections and re-sends write operations when + * the network connection is restored. + * + * However by default your write operations and cached data are only stored + * in-memory and will be lost when your app restarts. By setting this value to + * `YES`, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first Database reference and only needs to be called once per + * application. + * + */ +@property(nonatomic) BOOL persistenceEnabled NS_SWIFT_NAME(isPersistenceEnabled) + ; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. Cache sizes smaller than 1 MB or + * greater than 100 MB are not supported. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + * + * Note that this must be set before creating your first Database reference. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +/** + * Enables verbose diagnostic logging. + * + * @param enabled YES to enable logging, NO to disable. + */ ++ (void)setLoggingEnabled:(BOOL)enabled; + +/** Retrieve the Firebase Database SDK version. */ ++ (NSString *)sdkVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h new file mode 100644 index 00000000..82057aae --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h @@ -0,0 +1,395 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRDatabaseHandle is used to identify listeners of Firebase Database + * events. These handles are returned by observeEventType: and can later be + * passed to removeObserverWithHandle: to stop receiving updates. + */ +typedef NSUInteger FIRDatabaseHandle NS_SWIFT_NAME(DatabaseHandle); + +/** + * A FIRDatabaseQuery instance represents a query over the data at a particular + * location. + * + * You create one by calling one of the query methods (queryOrderedByChild:, + * queryStartingAtValue:, etc.) on a FIRDatabaseReference. The query methods can + * be chained to further specify the data you are interested in observing + */ +NS_SWIFT_NAME(DatabaseQuery) +@interface FIRDatabaseQuery : NSObject + +#pragma mark - Attach observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * Detach all blocks previously attached to this Firebase Database location with + * observeEventType:withBlock: + */ +- (void)removeAllObservers; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByValue: is used to generate a reference to a view of the data + * that's been sorted by child value. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child value. + */ +- (FIRDatabaseQuery *)queryOrderedByValue; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. This is most useful when implementing pagination in a + * case where multiple nodes can match the startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. This is most useful when implementing pagination in a case where + * multiple nodes can match the endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument and with their key equal to childKey. There will be + * at most one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The name of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the location of this query. + * + * @return A FIRDatabaseReference for the location of this query. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h new file mode 100644 index 00000000..c80b2f8b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h @@ -0,0 +1,861 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabase; + +/** + * A FIRDatabaseReference represents a particular location in your Firebase + * Database and can be used for reading or writing data to that Firebase + * Database location. + * + * This class is the starting point for all Firebase Database operations. After + * you've obtained your first FIRDatabaseReference via [FIRDatabase reference], + * you can use it to read data (ie. observeEventType:withBlock:), write data + * (ie. setValue:), and to create new FIRDatabaseReferences (ie. child:). + */ +NS_SWIFT_NAME(DatabaseReference) +@interface FIRDatabaseReference : FIRDatabaseQuery + +#pragma mark - Getting references to children locations + +/** + * Gets a FIRDatabaseReference for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') or a + * deeper slash-separated path (e.g. 'fred/name/first'). + * + * @param pathString A relative path from this location to the desired child + * location. + * @return A FIRDatabaseReference for the specified relative path. + */ +- (FIRDatabaseReference *)child:(NSString *)pathString; + +/** + * childByAutoId generates a new child location using a unique key and returns a + * FIRDatabaseReference to it. This is useful when the children of a Firebase + * Database location represent a list of items. + * + * The unique key generated by childByAutoId: is prefixed with a + * client-generated timestamp so that the resulting list will be + * chronologically-sorted. + * + * @return A FIRDatabaseReference for the generated location. + */ +- (FIRDatabaseReference *)childByAutoId; + +#pragma mark - Writing data + +/** Write data to this Firebase Database location. + +This will overwrite any data at this location and all child locations. + +Data types that can be set are: + +- NSString -- @"Hello World" +- NSNumber (also includes boolean) -- @YES, @43, @4.333 +- NSDictionary -- @{@"key": @"value", @"nested": @{@"another": @"value"} } +- NSArray + +The effect of the write will be visible immediately and the corresponding +events will be triggered. Synchronization of the data to the Firebase Database +servers will also be started. + +Passing null for the new value is equivalent to calling remove:; +all data at this location or any child location will be deleted. + +Note that setValue: will remove any priority stored at this location, so if +priority is meant to be preserved, you should use setValue:andPriority: instead. + +@param value The value to be written. + */ +- (void)setValue:(nullable id)value; + +/** + * The same as setValue: with a block that gets triggered after the write + * operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * The same as setValue: with an additional priority to be attached to the data + * being written. Priorities are used to order items. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + */ +- (void)setValue:(nullable id)value andPriority:(nullable id)priority; + +/** + * The same as setValue:andPriority: with a block that gets triggered after the + * write operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Remove the data at this Firebase Database location. Any data at child + * locations will also be deleted. + * + * The effect of the delete will be visible immediately and the corresponding + * events will be triggered. Synchronization of the delete to the Firebase + * Database servers will also be started. + * + * remove: is equivalent to calling setValue:nil + */ +- (void)removeValue; + +/** + * The same as remove: with a block that gets triggered after the remove + * operation has been committed to the Firebase Database servers. + * + * @param block The block to be called after the remove has been committed to + * the Firebase Database servers. + */ +- (void)removeValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Sets a priority for the data at this Firebase Database location. + * Priorities can be used to provide a custom ordering for the children at a + * location (if no priorities are specified, the children are ordered by key). + * + * You cannot set a priority on an empty location. For this reason + * setValue:andPriority: should be used when setting initial data with a + * specific priority and setPriority: should be used when updating the priority + * of existing data. + * + * Children are sorted based on this priority using the following rules: + * + * Children with no priority come first. + * Children with a number as their priority come next. They are sorted + * numerically by priority (small to large). Children with a string as their + * priority come last. They are sorted lexicographically by priority. Whenever + * two children have the same priority (including no priority), they are sorted + * by key. Numeric keys come first (sorted numerically), followed by the + * remaining keys (sorted lexicographically). + * + * Note that priorities are parsed and ordered as IEEE 754 double-precision + * floating-point numbers. Keys are always stored as strings and are treated as + * numbers only when they can be parsed as a 32-bit integer + * + * @param priority The priority to set at the specified location. + */ +- (void)setPriority:(nullable id)priority; + +/** + * The same as setPriority: with a block that is called once the priority has + * been committed to the Firebase Database servers. + * + * @param priority The priority to set at the specified location. + * @param block The block that is triggered after the priority has been written + * on the servers. + */ +- (void)setPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Updates the values at the specified paths in the dictionary without + * overwriting other keys at this location. + * + * @param values A dictionary of the keys to change and their new values + */ +- (void)updateChildValues:(NSDictionary *)values; + +/** + * The same as update: with a block that is called once the update has been + * committed to the Firebase Database servers + * + * @param values A dictionary of the keys to change and their new values + * @param block The block that is triggered after the update has been written on + * the Firebase Database servers + */ +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +#pragma mark - Attaching observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +/** + * Removes all observers at the current reference, but does not remove any + * observers at child references. removeAllObservers must be called again for + * each child reference where a listener was established to remove the + * observers. + */ +- (void)removeAllObservers; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument with a key equal to childKey. There will be at most + * one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The key of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Managing presence + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * onDisconnectSetValue: is especially useful for implementing "presence" + * systems, where a value should be changed or cleared when a user disconnects + * so that he appears "offline" to other users. + * + * @param value The value to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value; + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value andPriority:(id)priority; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValue is especially useful for implementing "presence" + * systems. + */ +- (void)onDisconnectRemoveValue; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValueWithCompletionBlock: is especially useful for + * implementing "presence" systems. + * + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectRemoveValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + * @param block A block that will be called once the operation has been queued + * up on the Firebase Database servers + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + */ +- (void)cancelDisconnectOperations; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + * + * @param block A block that will be triggered once the Firebase Database + * servers have acknowledged the cancel request. + */ +- (void)cancelDisconnectOperationsWithCompletionBlock: + (nullable void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +#pragma mark - Manual Connection Management + +/** + * Manually disconnect the Firebase Database client from the server and disable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * While offline, the Firebase Database client will no longer receive data + * updates from the server. However, all database operations performed locally + * will continue to immediately fire events, allowing your application to + * continue behaving normally. Additionally, each operation performed locally + * will automatically be queued and retried upon reconnection to the Firebase + * Database server. + * + * To reconnect to the Firebase Database server and begin receiving remote + * events, see goOnline( ). Once the connection is reestablished, the Firebase + * Database client will transmit the appropriate data and fire the appropriate + * events so that your client "catches up" automatically. + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOffline; + +/** + * Manually reestablish a connection to the Firebase Database server and enable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * This method should be used after invoking goOffline( ) to disable the active + * connection. Once reconnected, the Firebase Database client will automatically + * transmit the proper data and fire the appropriate events so that your client + * "catches up" automatically. + * + * To disconnect from the Firebase Database server, see goOffline( ). + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOnline; + +#pragma mark - Transactions + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot))completionBlock; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by return + * [FIRTransactionResult abort]. + * + * Since your block may be run multiple times, this client could see several + * immediate states that don't exist on the server. You can suppress those + * immediate states until the server confirms the final state of the + * transaction. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + * @param localEvents Set this to NO to suppress events raised for intermediate + * states, and only get events based on the final state of the transaction. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (nullable void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot)) + completionBlock + withLocalEvents:(BOOL)localEvents; + +#pragma mark - Retrieving String Representation + +/** + * Gets the absolute URL of this Firebase Database location. + * + * @return The absolute URL of the referenced Firebase Database location. + */ +- (NSString *)description; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the parent location. + * If this instance refers to the root of your Firebase Database, it has no + * parent, and therefore parent( ) will return null. + * + * @return A FIRDatabaseReference for the parent location. + */ +@property(strong, readonly, nonatomic, nullable) FIRDatabaseReference *parent; + +/** + * Gets a FIRDatabaseReference for the root location + * + * @return A new FIRDatabaseReference to root location. + */ +@property(strong, readonly, nonatomic) FIRDatabaseReference *root; + +/** + * Gets the last token in a Firebase Database location (e.g. 'fred' in + * https://SampleChat.firebaseIO-demo.com/users/fred) + * + * @return The key of the location this reference points to. + */ +@property(strong, readonly, nonatomic, nullable) NSString *key; + +/** + * Gets the URL for the Firebase Database location referenced by this + * FIRDatabaseReference. + * + * @return The url of the location this reference points to. + */ +@property(strong, readonly, nonatomic) NSString *URL; + +/** + * Gets the FIRDatabase instance associated with this reference. + * + * @return The FIRDatabase object for this reference. + */ +@property(strong, readonly, nonatomic) FIRDatabase *database; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h new file mode 100644 index 00000000..9797a67b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h @@ -0,0 +1,128 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRMutableData instance is populated with data from a Firebase Database + * location. When you are using runTransactionBlock:, you will be given an + * instance containing the current data at that location. Your block will be + * responsible for updating that instance to the data you wish to save at that + * location, and then returning using [FIRTransactionResult successWithValue:]. + * + * To modify the data, set its value property to any of the native types support + * by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that changes made to a child FIRMutableData instance will be visible to + * the parent. + */ +NS_SWIFT_NAME(MutableData) +@interface FIRMutableData : NSObject + +#pragma mark - Inspecting and navigating the data + +/** + * Returns boolean indicating whether this mutable data has children. + * + * @return YES if this data contains child nodes. + */ +- (BOOL)hasChildren; + +/** + * Indicates whether this mutable data has a child at the given path. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return YES if this data contains a child at the specified relative path + */ +- (BOOL)hasChildAtPath:(NSString *)path; + +/** + * Used to obtain a FIRMutableData instance that encapsulates the data at the + * given relative path. Note that changes made to the child will be visible to + * the parent. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return A FIRMutableData instance containing the data at the given path + */ +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path; + +#pragma mark - Properties + +/** + * To modify the data contained by this instance of FIRMutableData, set this to + * any of the native types supported by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that setting this value will override the priority at this location. + * + * @return The current data at this location as a native object + */ +@property(strong, nonatomic, nullable) id value; + +/** + * Set this property to update the priority of the data at this location. Can be + * set to the following types: + * + * + NSNumber + * + NSString + * + nil / NSNull to remove the priority + * + * @return The priority of the data at this location + */ +@property(strong, nonatomic, nullable) id priority; + +/** + * @return The number of child nodes at this location + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Used to iterate over the children at this location. You can use the native + * for .. in syntax: + * + * for (FIRMutableData* child in data.children) { + * ... + * } + * + * Note that this enumerator operates on an immutable copy of the child list. + * So, you can modify the instance during iteration, but the new additions will + * not be visible until you get a new enumerator. + */ +@property(readonly, nonatomic, strong) NSEnumerator *children; + +/** + * @return The key name of this node, or nil if it is the top-most location + */ +@property(readonly, nonatomic, strong, nullable) NSString *key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h new file mode 100644 index 00000000..5f57094f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Placeholder values you may write into Firebase Database as a value or + * priority that will automatically be populated by the Firebase Database + * server. + */ +NS_SWIFT_NAME(ServerValue) +@interface FIRServerValue : NSObject + +/** + * Placeholder value for the number of milliseconds since the Unix epoch + */ ++ (NSDictionary *)timestamp; + +/** + * Returns a placeholder value that can be used to atomically increment the + * current database value by the provided delta. + * + * The delta must be a long or double value. If the current value is not an + * integer or double, or if the data does not yet exist, the transformation will + * set the data to the delta value. If either of the delta value or the existing + * data are doubles, both values will be interpreted as doubles. Double + * arithmetic and representation of double values follow IEEE 754 semantics. If + * there is positive/negative integer overflow, the sum is calculated as a + * double. + * + * @param delta the amount to modify the current value atomically. + * @return a placeholder value for modifying data atomically server-side. + */ ++ (NSDictionary *)increment:(NSNumber *)delta NS_SWIFT_NAME(increment(_:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h new file mode 100644 index 00000000..7f5ccc18 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Used for runTransactionBlock:. An FIRTransactionResult instance is a + * container for the results of the transaction. + */ +NS_SWIFT_NAME(TransactionResult) +@interface FIRTransactionResult : NSObject + +/** + * Used for runTransactionBlock:. Indicates that the new value should be saved + * at this location + * + * @param value A FIRMutableData instance containing the new value to be set + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value; + +/** + * Used for runTransactionBlock:. Indicates that the current transaction should + * no longer proceed. + * + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)abort; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h new file mode 100644 index 00000000..ae6b9339 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FirebaseDatabase_h +#define FirebaseDatabase_h + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +#endif /* FirebaseDatabase_h */ diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h new file mode 100644 index 00000000..01ef28ce --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import "FWebSocketConnection.h" +#import + +@protocol FConnectionDelegate; + +@interface FConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + googleAppID:(NSString *)googleAppID + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive; + +// FWebSocketDelegate delegate methods +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end + +typedef enum { + DISCONNECT_REASON_SERVER_RESET = 0, + DISCONNECT_REASON_OTHER = 1 +} FDisconnectReason; + +@protocol FConnectionDelegate + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m new file mode 100644 index 00000000..8969173e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m @@ -0,0 +1,236 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FConstants.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +typedef enum { + REALTIME_STATE_CONNECTING = 0, + REALTIME_STATE_CONNECTED = 1, + REALTIME_STATE_DISCONNECTED = 2, +} FConnectionState; + +@interface FConnection () { + FConnectionState state; +} + +@property(nonatomic, strong) FWebSocketConnection *conn; +@property(nonatomic, strong) FRepoInfo *repoInfo; + +@end + +#pragma mark - +#pragma mark FConnection implementation + +@implementation FConnection + +@synthesize delegate; +@synthesize conn; +@synthesize repoInfo; + +#pragma mark - +#pragma mark Initializers + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + googleAppID:googleAppID + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + state = REALTIME_STATE_CONNECTING; + self.repoInfo = aRepoInfo; + self.conn = [[FWebSocketConnection alloc] initWith:self.repoInfo + andQueue:queue + googleAppID:googleAppID + lastSessionID:lastSessionID]; + self.conn.delegate = self; + } + return self; +} + +#pragma mark - +#pragma mark Public method implementation + +- (void)open { + FFLog(@"I-RDB082001", @"Calling open in FConnection"); + [self.conn open]; +} + +- (void)closeWithReason:(FDisconnectReason)reason { + if (state != REALTIME_STATE_DISCONNECTED) { + FFLog(@"I-RDB082002", @"Closing realtime connection."); + state = REALTIME_STATE_DISCONNECTED; + + if (self.conn) { + FFLog(@"I-RDB082003", @"Calling close again."); + [self.conn close]; + self.conn = nil; + } + + [self.delegate onDisconnect:self withReason:reason]; + } +} + +- (void)close { + [self closeWithReason:DISCONNECT_REASON_OTHER]; +} + +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive { + // since this came from the persistent connection, wrap it in a data message + // envelope + NSDictionary *msg = @{ + kFWPRequestType : kFWPRequestTypeData, + kFWPRequestDataPayload : dataMsg + }; + [self sendData:msg sensitive:sensitive]; +} + +#pragma mark - +#pragma mark Helpers + +- (void)sendData:(NSDictionary *)data sensitive:(BOOL)sensitive { + if (state != REALTIME_STATE_CONNECTED) { + @throw [[NSException alloc] + initWithName:@"InvalidConnectionState" + reason:@"Tried to send data on an unconnected FConnection" + userInfo:nil]; + } else { + if (sensitive) { + FFLog(@"I-RDB082004", @"Sending data (contents hidden)"); + } else { + FFLog(@"I-RDB082005", @"Sending: %@", data); + } + [self.conn send:data]; + } +} + +#pragma mark - +#pragma mark FWebSocketConnectinDelegate implementation + +// Corresponds to onConnectionLost in JS +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected { + + self.conn = nil; + if (!everConnected && state == REALTIME_STATE_CONNECTING) { + FFLog(@"I-RDB082006", @"Realtime connection failed."); + + // Since we failed to connect at all, clear any cached entry for this + // namespace in case the machine went away + [self.repoInfo clearInternalHostCache]; + } else if (state == REALTIME_STATE_CONNECTED) { + FFLog(@"I-RDB082007", @"Realtime connection lost."); + } + + [self close]; +} + +// Corresponds to onMessageReceived in JS +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message { + NSString *rawMessageType = + [message objectForKey:kFWPAsyncServerEnvelopeType]; + if (rawMessageType != nil) { + if ([rawMessageType isEqualToString:kFWPAsyncServerDataMessage]) { + [self onDataMessage:[message + objectForKey:kFWPAsyncServerEnvelopeData]]; + } else if ([rawMessageType + isEqualToString:kFWPAsyncServerControlMessage]) { + [self onControl:[message objectForKey:kFWPAsyncServerEnvelopeData]]; + } else { + FFLog(@"I-RDB082008", @"Unrecognized server packet type: %@", + rawMessageType); + } + } else { + FFLog(@"I-RDB082009", @"Unrecognized raw server packet received: %@", + message); + } +} + +- (void)onDataMessage:(NSDictionary *)message { + // we don't do anything with data messages, just kick them up a level + FFLog(@"I-RDB082010", @"Got data message: %@", message); + [self.delegate onDataMessage:self withMessage:message]; +} + +- (void)onControl:(NSDictionary *)message { + FFLog(@"I-RDB082011", @"Got control message: %@", message); + NSString *type = [message objectForKey:kFWPAsyncServerControlMessageType]; + if ([type isEqualToString:kFWPAsyncServerControlMessageShutdown]) { + NSString *reason = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onConnectionShutdownWithReason:reason]; + } else if ([type isEqualToString:kFWPAsyncServerControlMessageReset]) { + NSString *host = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onReset:host]; + } else if ([type isEqualToString:kFWPAsyncServerHello]) { + NSDictionary *handshakeData = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onHandshake:handshakeData]; + } else { + FFLog(@"I-RDB082012", + @"Unknown control message returned from server: %@", message); + } +} + +- (void)onConnectionShutdownWithReason:(NSString *)reason { + FFLog(@"I-RDB082013", + @"Connection shutdown command received. Shutting down..."); + + [self.delegate onKill:self withReason:reason]; + [self close]; +} + +- (void)onHandshake:(NSDictionary *)handshake { + NSNumber *timestamp = + [handshake objectForKey:kFWPAsyncServerHelloTimestamp]; + // NSString* version = [handshake + // objectForKey:kFWPAsyncServerHelloVersion]; + NSString *host = [handshake objectForKey:kFWPAsyncServerHelloConnectedHost]; + NSString *sessionID = [handshake objectForKey:kFWPAsyncServerHelloSession]; + + self.repoInfo.internalHost = host; + + if (state == REALTIME_STATE_CONNECTING) { + [self.conn start]; + [self onConnection:self.conn readyAtTime:timestamp sessionID:sessionID]; + } +} + +- (void)onConnection:(FWebSocketConnection *)conn + readyAtTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB082014", @"Realtime connection established"); + state = REALTIME_STATE_CONNECTED; + + [self.delegate onReady:self atTime:timestamp sessionID:sessionID]; +} + +- (void)onReset:(NSString *)host { + FFLog( + @"I-RDB082015", + @"Got a reset; killing connection to: %@; Updating internalHost to: %@", + repoInfo.internalHost, host); + self.repoInfo.internalHost = host; + + // Explicitly close the connection with SERVER_RESET so calling code knows + // to reconnect immediately. + [self closeWithReason:DISCONNECT_REASON_SERVER_RESET]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h new file mode 100644 index 00000000..999c3944 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSRWebSocket.h" +#import "FUtilities.h" +#import + +@protocol FWebSocketDelegate; + +@interface FWebSocketConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + googleAppID:(NSString *)googleAppID + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)start; +- (void)send:(NSDictionary *)dictionary; + +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean; + +@end + +@protocol FWebSocketDelegate + +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m new file mode 100644 index 00000000..0b964743 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m @@ -0,0 +1,348 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. + +#import + +#import "FConstants.h" +#import "FIRDatabaseReference.h" +#import "FIRDatabase_Private.h" +#import "FStringUtilities.h" +#import "FWebSocketConnection.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FWebSocketConnection () { + NSMutableString *frame; + BOOL everConnected; + BOOL isClosed; + NSTimer *keepAlive; +} + +- (void)shutdown; +- (void)onClosed; +- (void)closeIfNeverConnected; + +@property(nonatomic, strong) FSRWebSocket *webSocket; +@property(nonatomic, strong) NSNumber *connectionId; +@property(nonatomic, readwrite) int totalFrames; +@property(nonatomic, readonly) BOOL buffering; +@property(nonatomic, readonly) NSString *userAgent; +@property(nonatomic) dispatch_queue_t dispatchQueue; + +- (void)nop:(NSTimer *)timer; + +@end + +@implementation FWebSocketConnection + +@synthesize delegate; +@synthesize webSocket; +@synthesize connectionId; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + googleAppID:(NSString *)googleAppID + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + everConnected = NO; + isClosed = NO; + self.connectionId = [FUtilities LUIDGenerator]; + self.totalFrames = 0; + self.dispatchQueue = queue; + frame = nil; + + NSString *connectionUrl = + [repoInfo connectionURLWithLastSessionID:lastSessionID]; + NSString *ua = [self userAgent]; + FFLog(@"I-RDB083001", @"(wsc:%@) Connecting to: %@ as %@", + self.connectionId, connectionUrl, ua); + + NSURLRequest *req = [[NSURLRequest alloc] + initWithURL:[[NSURL alloc] initWithString:connectionUrl]]; + self.webSocket = [[FSRWebSocket alloc] initWithURLRequest:req + queue:queue + googleAppID:googleAppID + andUserAgent:ua]; + [self.webSocket setDelegateDispatchQueue:queue]; + self.webSocket.delegate = self; + } + return self; +} + +- (NSString *)userAgent { + NSString *systemVersion; + NSString *deviceName; + BOOL hasUiDeviceClass = NO; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + Class uiDeviceClass = NSClassFromString(@"UIDevice"); + if (uiDeviceClass) { + systemVersion = [uiDeviceClass currentDevice].systemVersion; + deviceName = [uiDeviceClass currentDevice].model; + hasUiDeviceClass = YES; + } +#endif + + if (!hasUiDeviceClass) { + NSDictionary *systemVersionDictionary = [NSDictionary + dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + systemVersion = + [systemVersionDictionary objectForKey:@"ProductVersion"]; + deviceName = [systemVersionDictionary objectForKey:@"ProductName"]; + } + + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + + // Sanitize '/'s in deviceName and bundleIdentifier for stats + deviceName = [FStringUtilities sanitizedForUserAgent:deviceName]; + bundleIdentifier = + [FStringUtilities sanitizedForUserAgent:bundleIdentifier]; + + // Firebase/5/__//{device model / + // os (Mac OS X, iPhone, etc.}_ + NSString *ua = [NSString + stringWithFormat:@"Firebase/%@/%@/%@/%@_%@", kWebsocketProtocolVersion, + [FIRDatabase buildVersion], systemVersion, deviceName, + bundleIdentifier]; + return ua; +} + +- (BOOL)buffering { + return frame != nil; +} + +#pragma mark - +#pragma mark Public FWebSocketConnection methods + +- (void)open { + FFLog(@"I-RDB083002", @"(wsc:%@) FWebSocketConnection open.", + self.connectionId); + assert(delegate); + everConnected = NO; + // TODO Assert url + [self.webSocket open]; + dispatch_time_t when = dispatch_time( + DISPATCH_TIME_NOW, kWebsocketConnectTimeout * NSEC_PER_SEC); + dispatch_after(when, self.dispatchQueue, ^{ + [self closeIfNeverConnected]; + }); +} + +- (void)close { + FFLog(@"I-RDB083003", @"(wsc:%@) FWebSocketConnection is being closed.", + self.connectionId); + isClosed = YES; + [self.webSocket close]; +} + +- (void)start { + // Start is a no-op for websockets. +} + +- (void)send:(NSDictionary *)dictionary { + + [self resetKeepAlive]; + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary + options:kNilOptions + error:nil]; + + NSString *data = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + + NSArray *dataSegs = [FUtilities splitString:data + intoMaxSize:kWebsocketMaxFrameSize]; + + // First send the header so the server knows how many segments are + // forthcoming + if (dataSegs.count > 1) { + [self.webSocket + send:[NSString + stringWithFormat:@"%u", (unsigned int)dataSegs.count]]; + } + + // Then, actually send the segments. + for (NSString *segment in dataSegs) { + [self.webSocket send:segment]; + } +} + +- (void)nop:(NSTimer *)timer { + if (!isClosed) { + FFLog(@"I-RDB083004", @"(wsc:%@) nop", self.connectionId); + [self.webSocket send:@"0"]; + } else { + FFLog(@"I-RDB083005", + @"(wsc:%@) No more websocket; invalidating nop timer.", + self.connectionId); + [timer invalidate]; + } +} + +- (void)handleNewFrameCount:(int)numFrames { + self.totalFrames = numFrames; + frame = [[NSMutableString alloc] initWithString:@""]; + FFLog(@"I-RDB083006", @"(wsc:%@) handleNewFrameCount: %d", + self.connectionId, self.totalFrames); +} + +- (NSString *)extractFrameCount:(NSString *)message { + if ([message length] <= 4) { + int frameCount = [message intValue]; + if (frameCount > 0) { + [self handleNewFrameCount:frameCount]; + return nil; + } + } + [self handleNewFrameCount:1]; + return message; +} + +- (void)appendFrame:(NSString *)message { + [frame appendString:message]; + self.totalFrames = self.totalFrames - 1; + + if (self.totalFrames == 0) { + // Call delegate and pass an immutable version of the frame + NSDictionary *json = [NSJSONSerialization + JSONObjectWithData:[frame dataUsingEncoding:NSUTF8StringEncoding] + options:kNilOptions + error:nil]; + frame = nil; + FFLog(@"I-RDB083007", + @"(wsc:%@) handleIncomingFrame sending complete frame: %d", + self.connectionId, self.totalFrames); + + @autoreleasepool { + [self.delegate onMessage:self withMessage:json]; + } + } +} + +- (void)handleIncomingFrame:(NSString *)message { + [self resetKeepAlive]; + if (self.buffering) { + [self appendFrame:message]; + } else { + NSString *remaining = [self extractFrameCount:message]; + if (remaining) { + [self appendFrame:remaining]; + } + } +} + +#pragma mark - +#pragma mark SRWebSocketDelegate implementation +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message { + [self handleIncomingFrame:message]; +} + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket { + FFLog(@"I-RDB083008", @"(wsc:%@) webSocketDidOpen", self.connectionId); + + everConnected = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + self->keepAlive = + [NSTimer scheduledTimerWithTimeInterval:kWebsocketKeepaliveInterval + target:self + selector:@selector(nop:) + userInfo:nil + repeats:YES]; + FFLog(@"I-RDB083009", @"(wsc:%@) nop timer kicked off", + self.connectionId); + }); +} + +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error { + FFLog(@"I-RDB083010", @"(wsc:%@) didFailWithError didFailWithError: %@", + self.connectionId, [error description]); + [self onClosed]; +} + +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean { + FFLog(@"I-RDB083011", @"(wsc:%@) didCloseWithCode: %ld %@", + self.connectionId, (long)code, reason); + [self onClosed]; +} + +#pragma mark - +#pragma mark Private methods + +/** + * Note that the close / onClosed / shutdown cycle here is a little different + * from the javascript client. In order to properly handle deallocation, no + * close-related action is taken at a higher level until we have received + * notification from the websocket itself that it is closed. Otherwise, we end + * up deallocating this class and the FConnection class before the websocket has + * a change to call some of its delegate methods. So, since close is the + * external close handler, we just set a flag saying not to call our own + * delegate method and close the websocket. That will trigger a callback into + * this class that can then do things like clean up the keepalive timer. + */ + +- (void)closeIfNeverConnected { + if (!everConnected) { + FFLog(@"I-RDB083012", @"(wsc:%@) Websocket timed out on connect", + self.connectionId); + [self.webSocket close]; + } +} + +- (void)shutdown { + isClosed = YES; + + // Call delegate methods + [self.delegate onDisconnect:self wasEverConnected:everConnected]; +} + +- (void)onClosed { + if (!isClosed) { + FFLog(@"I-RDB083013", @"Websocket is closing itself"); + [self shutdown]; + } + self.webSocket = nil; + if (keepAlive.isValid) { + [keepAlive invalidate]; + } +} + +- (void)resetKeepAlive { + NSDate *newTime = + [NSDate dateWithTimeIntervalSinceNow:kWebsocketKeepaliveInterval]; + // Calling setFireDate is actually kinda' expensive, so wait at least 5 + // seconds before updating it. + if ([newTime timeIntervalSinceDate:keepAlive.fireDate] > 5) { + FFLog(@"I-RDB083014", @"(wsc:%@) resetting keepalive, to %@ ; old: %@", + self.connectionId, newTime, [keepAlive fireDate]); + [keepAlive setFireDate:newTime]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h new file mode 100644 index 00000000..cc3239e8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FNode.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@class FNamedNode; + +@interface FChildrenNode : NSObject + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren; +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren; + +// FChildrenNode specific methods + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +@property(nonatomic, strong) FImmutableSortedDictionary *children; +@property(nonatomic, strong) id priorityNode; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m new file mode 100644 index 00000000..bd02bf8b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m @@ -0,0 +1,418 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPriorityIndex.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FTransformedEnumerator.h" +#import "FUtilities.h" + +@interface FChildrenNode () +@property(nonatomic, strong) NSString *lazyHash; +@end + +@implementation FChildrenNode + +// Note: The only reason we allow nil priority is to for EmptyNode, since we +// can't use EmptyNode as the priority of EmptyNode. We might want to consider +// making EmptyNode its own class instead of an empty ChildrenNode. + +- (id)init { + return [self + initWithPriority:nil + children:[FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities + keyComparator]]]; +} + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren { + return [self initWithPriority:nil children:someChildren]; +} + +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren { + if (someChildren.isEmpty && aPriority != nil && ![aPriority isEmpty]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't create empty node with priority!"]; + } + self = [super init]; + if (self) { + self.children = someChildren; + self.priorityNode = aPriority; + } + return self; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return NO; +} + +- (id)getPriority { + if (self.priorityNode) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)updatePriority:(id)aPriority { + if ([self.children isEmpty]) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:aPriority + children:self.children]; + } +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + id child = [self.children objectForKey:childName]; + return (child == nil) ? [FEmptyNode emptyNode] : child; + } +} + +- (id)getChild:(FPath *)path { + NSString *front = [path getFront]; + if (front == nil) { + return self; + } else { + return [[self getImmediateChild:front] getChild:[path popFront]]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return ![self getImmediateChild:childName].isEmpty; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + NSAssert(newChildNode != nil, @"Should always be passing nodes."); + + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else { + FImmutableSortedDictionary *newChildren; + if (newChildNode.isEmpty) { + newChildren = [self.children removeObjectForKey:childName]; + } else { + newChildren = [self.children setObject:newChildNode + forKey:childName]; + } + if (newChildren.isEmpty) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:self.getPriority + children:newChildren]; + } + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + id newImmediateChild = + [[self getImmediateChild:front] updateChild:[path popFront] + withNewChild:newChildNode]; + return [self updateImmediateChild:front withNewChild:newImmediateChild]; + } +} + +- (BOOL)isEmpty { + return [self.children isEmpty]; +} + +- (int)numChildren { + return [self.children count]; +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if ([self isEmpty]) { + return [NSNull null]; + } + + __block int numKeys = 0; + __block NSInteger maxKey = 0; + __block BOOL allIntegerKeys = YES; + + NSMutableDictionary *obj = + [[NSMutableDictionary alloc] initWithCapacity:[self.children count]]; + [self enumerateChildrenUsingBlock:^(NSString *key, id childNode, + BOOL *stop) { + [obj setObject:[childNode valForExport:exp] forKey:key]; + + numKeys++; + + // If we already found a string key, don't bother with any of this + if (!allIntegerKeys) { + return; + } + + // Treat leading zeroes that are not exactly "0" as strings + NSString *firstChar = [key substringWithRange:NSMakeRange(0, 1)]; + if ([firstChar isEqualToString:@"0"] && [key length] > 1) { + allIntegerKeys = NO; + } else { + NSNumber *keyAsNum = [FUtilities intForString:key]; + if (keyAsNum != nil) { + NSInteger keyAsInt = [keyAsNum integerValue]; + if (keyAsInt > maxKey) { + maxKey = keyAsInt; + } + } else { + allIntegerKeys = NO; + } + } + }]; + + if (!exp && allIntegerKeys && maxKey < 2 * numKeys) { + // convert to an array + NSMutableArray *array = + [[NSMutableArray alloc] initWithCapacity:maxKey + 1]; + for (int i = 0; i <= maxKey; ++i) { + NSString *keyString = [NSString stringWithFormat:@"%i", i]; + id child = obj[keyString]; + if (child != nil) { + [array addObject:child]; + } else { + [array addObject:[NSNull null]]; + } + } + return array; + } else { + + if (exp && [self getPriority] != nil && !self.getPriority.isEmpty) { + obj[kPayloadPriority] = [self.getPriority val]; + } + + return obj; + } +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + + if (!self.getPriority.isEmpty) { + [toHash appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:(FLeafNode *) + self.getPriority + toString:toHash + hashVersion:FDataHashVersionV1]; + [toHash appendString:@":"]; + } + + __block BOOL sawPriority = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + sawPriority = sawPriority || [[node getPriority] isEmpty]; + *stop = sawPriority; + }]; + if (sawPriority) { + NSMutableArray *array = [NSMutableArray array]; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + FNamedNode *namedNode = [[FNamedNode alloc] initWithName:key + andNode:node]; + [array addObject:namedNode]; + }]; + [array sortUsingComparator:^NSComparisonResult( + FNamedNode *namedNode1, FNamedNode *namedNode2) { + return + [[FPriorityIndex priorityIndex] compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + [array enumerateObjectsUsingBlock:^(FNamedNode *namedNode, + NSUInteger idx, BOOL *stop) { + NSString *childHash = [namedNode.node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", namedNode.name, childHash]; + } + }]; + } else { + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + NSString *childHash = [node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", key, childHash]; + } + }]; + } + self.lazyHash = [toHash isEqualToString:@""] + ? @"" + : [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + // children nodes come last, unless this is actually an empty node, then we + // come first. + if (self.isEmpty) { + if (other.isEmpty) { + return NSOrderedSame; + } else { + return NSOrderedAscending; + } + } else if (other.isLeafNode || other.isEmpty) { + return NSOrderedDescending; + } else if (other == [FMaxNode maxNode]) { + return NSOrderedAscending; + } else { + // Must be another node with children. + return NSOrderedSame; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other == nil) { + return NO; + } else if (other.isLeafNode) { + return NO; + } else if (self.isEmpty && [other isEmpty]) { + // Empty nodes do not have priority + return YES; + } else { + FChildrenNode *otherChildrenNode = other; + if (![self.getPriority isEqual:other.getPriority]) { + return NO; + } else if (self.children.count == otherChildrenNode.children.count) { + __block BOOL equal = YES; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + id child = [otherChildrenNode getImmediateChild:key]; + if (![child isEqual:node]) { + equal = NO; + *stop = YES; + } + }]; + return equal; + } else { + return NO; + } + } +} + +- (NSUInteger)hash { + __block NSUInteger hashCode = 0; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + hashCode = 31 * hashCode + key.hash; + hashCode = 17 * hashCode + node.hash; + }]; + return 17 * hashCode + self.priorityNode.hash; +} + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + if ([self.getPriority isEmpty]) { + [self enumerateChildrenUsingBlock:block]; + } else { + __block BOOL passedPriorityKey = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (!passedPriorityKey && + [FUtilities compareKey:key + toKey:@".priority"] == NSOrderedDescending) { + passedPriorityKey = YES; + BOOL stopAfterPriority = NO; + block(@".priority", [self getPriority], &stopAfterPriority); + if (stopAfterPriority) + return; + } + block(key, node, stop); + }]; + } +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + [self.children enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self.children enumerateKeysAndObjectsReverse:reverse usingBlock:block]; +} + +- (NSEnumerator *)childEnumerator { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.children.keyEnumerator + andTransform:^id(NSString *key) { + return [FNamedNode nodeWithName:key + node:[self getImmediateChild:key]]; + }]; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return [self.children getPredecessorKey:childKey]; +} + +#pragma mark - +#pragma mark FChildrenNode specific methods + +- (id)childrenGetter:(id)key { + return [self.children objectForKey:key]; +} + +- (FNamedNode *)firstChild { + NSString *childKey = self.children.minKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +- (FNamedNode *)lastChild { + NSString *childKey = self.children.maxKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h new file mode 100644 index 00000000..47de66f5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableTree; +@protocol FNode; +@class FPath; + +/** + * This class holds a collection of writes that can be applied to nodes in + * unison. It abstracts away the logic with dealing with priority writes and + * multiple nested writes. At any given path, there is only allowed to be one + * write modifying that path. Any write to an existing path or shadowing an + * existing path will modify that existing write to reflect the write added. + */ +@interface FCompoundWrite : NSObject + +- (id)initWithWriteTree:(FImmutableTree *)tree; + +/** + * Creates a compound write with NSDictionary from path string to object + */ ++ (FCompoundWrite *)compoundWriteWithValueDictionary:(NSDictionary *)dictionary; +/** + * Creates a compound write with NSDictionary from path string to node + */ ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary; + ++ (FCompoundWrite *)emptyWrite; + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path; +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key; +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)node + atPath:(FPath *)path; +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path; +- (id)rootWrite; +- (BOOL)hasCompleteWriteAtPath:(FPath *)path; +- (id)completeNodeAtPath:(FPath *)path; +- (NSArray *)completeChildren; +- (NSDictionary *)childCompoundWrites; +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path; +- (id)applyToNode:(id)node; +- (void)enumerateWrites:(void (^)(FPath *path, id node, + BOOL *stop))block; + +- (NSDictionary *)valForExport:(BOOL)exportFormat; + +- (BOOL)isEmpty; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m new file mode 100644 index 00000000..bc40b2bd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundWrite.h" +#import "FImmutableTree.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" + +@interface FCompoundWrite () +@property(nonatomic, strong) FImmutableTree *writeTree; +@end + +@implementation FCompoundWrite + +- (id)initWithWriteTree:(FImmutableTree *)tree { + self = [super init]; + if (self) { + self.writeTree = tree; + } + return self; +} + ++ (FCompoundWrite *)compoundWriteWithValueDictionary: + (NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id value, BOOL *stop) { + id node = [FSnapshotUtilities nodeFrom:value]; + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id node, BOOL *stop) { + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)emptyWrite { + static dispatch_once_t pred = 0; + static FCompoundWrite *empty = nil; + dispatch_once(&pred, ^{ + empty = [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:nil]]; + }); + return empty; +} + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path { + if (path.isEmpty) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:node]]; + } else { + FTuplePathValue *rootMost = + [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path + to:path]; + id value = [rootMost.value updateChild:relativePath + withNewChild:node]; + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree setValue:value + atPath:rootMost.path]]; + } else { + FImmutableTree *subtree = + [[FImmutableTree alloc] initWithValue:node]; + FImmutableTree *newWriteTree = [self.writeTree setTree:subtree + atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } + } +} + +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key { + return [self addWrite:node atPath:[[FPath alloc] initWith:key]]; +} + +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)compoundWrite + atPath:(FPath *)path { + __block FCompoundWrite *newWrite = self; + [compoundWrite.writeTree forEach:^(FPath *childPath, id value) { + newWrite = [newWrite addWrite:value atPath:[path child:childPath]]; + }]; + return newWrite; +} + +/** + * Will remove a write at the given path and deeper paths. This will + * not modify a write at a higher location, which must be removed by + * calling this method with that path. + * @param path The path at which a write and all deeper writes should be + * removed. + * @return The new FWriteCompound with the removed path. + */ +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return [FCompoundWrite emptyWrite]; + } else { + FImmutableTree *newWriteTree = + [self.writeTree setTree:[FImmutableTree empty] atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } +} + +/** + * Returns whether this FCompoundWrite will fully overwrite a node at a given + * location and can therefore be considered "complete". + * @param path The path to check for + * @return Whether there is a complete write at that path. + */ +- (BOOL)hasCompleteWriteAtPath:(FPath *)path { + return [self completeNodeAtPath:path] != nil; +} + +/** + * Returns a node for a path if and only if the node is a "complete" overwrite + * at that path. This will not aggregate writes from depeer paths, but will + * return child nodes from a more shallow path. + * @param path The path to get a complete write + * @return The node if complete at that path, or nil otherwise. + */ +- (id)completeNodeAtPath:(FPath *)path { + FTuplePathValue *rootMost = [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path to:path]; + return [rootMost.value getChild:relativePath]; + } else { + return nil; + } +} + +// TODO: change into traversal method... +- (NSArray *)completeChildren { + NSMutableArray *children = [[NSMutableArray alloc] init]; + if (self.writeTree.value != nil) { + id node = self.writeTree.value; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [children addObject:[[FNamedNode alloc] initWithName:key + andNode:node]]; + }]; + } else { + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value != nil) { + [children addObject:[[FNamedNode alloc] + initWithName:childKey + andNode:childTree.value]]; + } + }]; + } + return children; +} + +// TODO: change into enumarate method +- (NSDictionary *)childCompoundWrites { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *childWrite, BOOL *stop) { + dict[key] = [[FCompoundWrite alloc] initWithWriteTree:childWrite]; + }]; + return dict; +} + +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + id shadowingNode = [self completeNodeAtPath:path]; + if (shadowingNode != nil) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] + initWithValue:shadowingNode]]; + } else { + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree subtreeAtPath:path]]; + } + } +} + +- (id)applySubtreeWrite:(FImmutableTree *)subtreeWrite + atPath:(FPath *)relativePath + toNode:(id)node { + if (subtreeWrite.value != nil) { + // Since a write there is always a leaf, we're done here. + return [node updateChild:relativePath withNewChild:subtreeWrite.value]; + } else { + __block id priorityWrite = nil; + __block id blockNode = node; + [subtreeWrite.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childKey isEqualToString:@".priority"]) { + // Apply priorities at the end so we don't update priorities + // for either empty nodes or forget to apply priorities to + // empty nodes that are later filled. + NSAssert(childTree.value != nil, + @"Priority writes must always be leaf nodes"); + priorityWrite = childTree.value; + } else { + blockNode = [self + applySubtreeWrite:childTree + atPath:[relativePath childFromString:childKey] + toNode:blockNode]; + } + }]; + // If there was a priority write, we only apply it if the node is not + // empty + if (![blockNode getChild:relativePath].isEmpty && + priorityWrite != nil) { + blockNode = [blockNode + updateChild:[relativePath childFromString:@".priority"] + withNewChild:priorityWrite]; + } + return blockNode; + } +} + +- (void)enumerateWrites:(void (^)(FPath *, id, BOOL *))block { + __block BOOL stop = NO; + // TODO: add stop to tree iterator... + [self.writeTree forEach:^(FPath *path, id value) { + if (!stop) { + block(path, value, &stop); + } + }]; +} + +/** + * Applies this FCompoundWrite to a node. The node is returned with all writes + * from this FCompoundWrite applied to the node. + * @param node The node to apply this FCompoundWrite to + * @return The node with all writes applied + */ +- (id)applyToNode:(id)node { + return [self applySubtreeWrite:self.writeTree + atPath:[FPath empty] + toNode:node]; +} + +/** + * Return true if this CompoundWrite is empty and therefore does not modify any + * nodes. + * @return Whether this CompoundWrite is empty + */ +- (BOOL)isEmpty { + return self.writeTree.isEmpty; +} + +- (id)rootWrite { + return self.writeTree.value; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FCompoundWrite class]]) { + return NO; + } + FCompoundWrite *other = (FCompoundWrite *)object; + return + [[self valForExport:YES] isEqualToDictionary:[other valForExport:YES]]; +} + +- (NSUInteger)hash { + return [[self valForExport:YES] hash]; +} + +- (NSDictionary *)valForExport:(BOOL)exportFormat { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + [self.writeTree forEach:^(FPath *path, id value) { + dictionary[path.wireFormat] = [value valForExport:exportFormat]; + }]; + return dictionary; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h new file mode 100644 index 00000000..d002df09 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FEmptyNode : NSObject + ++ (id)emptyNode; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m new file mode 100644 index 00000000..bde3a8ab --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEmptyNode.h" +#import "FChildrenNode.h" + +@implementation FEmptyNode + ++ (id)emptyNode { + static FChildrenNode *empty = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + empty = [[FChildrenNode alloc] init]; + }); + return empty; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h new file mode 100644 index 00000000..b161dea5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" + +/** + * Represents a node together with an index. The index and node are updated in + * unison. In the case where the index does not affect the ordering (i.e. the + * ordering is identical to the key ordering) this class uses a fallback index + * to save memory. Everything operating on the index must special case the + * fallback index. + */ +@interface FIndexedNode : NSObject + +@property(nonatomic, strong, readonly) id node; + ++ (FIndexedNode *)indexedNodeWithNode:(id)node; ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index; + +- (BOOL)hasIndex:(id)index; +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode; +- (FIndexedNode *)updatePriority:(id)priority; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index; + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m new file mode 100644 index 00000000..dafe9c3a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m @@ -0,0 +1,218 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedNode.h" + +#import "FChildrenNode.h" +#import "FImmutableSortedSet.h" +#import "FIndex.h" +#import "FKeyIndex.h" +#import "FPriorityIndex.h" + +static FImmutableSortedSet *FALLBACK_INDEX; + +@interface FIndexedNode () + +@property(nonatomic, strong) id node; +/** + * The indexed set is initialized lazily to prevent creation when it is not + * needed + */ +@property(nonatomic, strong) FImmutableSortedSet *indexed; +@property(nonatomic, strong) id index; + +@end + +@implementation FIndexedNode + ++ (FImmutableSortedSet *)fallbackIndex { + static FImmutableSortedSet *fallbackIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + fallbackIndex = [[FImmutableSortedSet alloc] init]; + }); + return fallbackIndex; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node { + return [[FIndexedNode alloc] initWithNode:node + index:[FPriorityIndex priorityIndex]]; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index { + return [[FIndexedNode alloc] initWithNode:node index:index]; +} + +- (id)initWithNode:(id)node index:(id)index { + // Initialize indexed lazily + return [self initWithNode:node index:index indexed:nil]; +} + +- (id)initWithNode:(id)node + index:(id)index + indexed:(FImmutableSortedSet *)indexed { + self = [super init]; + if (self != nil) { + self->_node = node; + self->_index = index; + self->_indexed = indexed; + } + return self; +} + +- (void)ensureIndexed { + if (!self.indexed) { + if ([self.index isEqual:[FKeyIndex keyIndex]]) { + self.indexed = [FIndexedNode fallbackIndex]; + } else { + __block BOOL sawChild = NO; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + sawChild = sawChild || [self.index isDefinedOn:node]; + *stop = sawChild; + }]; + if (sawChild) { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FNamedNode *namedNode = + [[FNamedNode alloc] initWithName:key andNode:node]; + dict[namedNode] = [NSNull null]; + }]; + // Make sure to assign index here, because the comparator will + // be retained and using self will cause a cycle + id index = self.index; + self.indexed = [FImmutableSortedSet + setWithKeysFromDictionary:dict + comparator:^NSComparisonResult( + FNamedNode *namedNode1, + FNamedNode *namedNode2) { + return [index compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + } else { + self.indexed = [FIndexedNode fallbackIndex]; + } + } + } +} + +- (BOOL)hasIndex:(id)index { + return [self.index isEqual:index]; +} + +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode { + id newNode = [self.node updateImmediateChild:key + withNewChild:newChildNode]; + if (self.indexed == [FIndexedNode fallbackIndex] && + ![self.index isDefinedOn:newChildNode]) { + // doesn't affect the index, no need to create an index + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:[FIndexedNode fallbackIndex]]; + } else if (!self.indexed || self.indexed == [FIndexedNode fallbackIndex]) { + // No need to index yet, index lazily + return [[FIndexedNode alloc] initWithNode:newNode index:self.index]; + } else { + id oldChild = [self.node getImmediateChild:key]; + FImmutableSortedSet *newIndexed = [self.indexed + removeObject:[FNamedNode nodeWithName:key node:oldChild]]; + if (![newChildNode isEmpty]) { + newIndexed = [newIndexed + addObject:[FNamedNode nodeWithName:key node:newChildNode]]; + } + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:newIndexed]; + } +} + +- (FIndexedNode *)updatePriority:(id)priority { + return + [[FIndexedNode alloc] initWithNode:[self.node updatePriority:priority] + index:self.index + indexed:self.indexed]; +} + +- (FNamedNode *)firstChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) firstChild]; + } else { + return self.indexed.firstObject; + } + } +} + +- (FNamedNode *)lastChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) lastChild]; + } else { + return self.indexed.lastObject; + } + } +} + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index { + if (![self.index isEqual:index]) { + [NSException raise:NSInvalidArgumentException + format:@"Index not available in IndexedNode!"]; + } + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node predecessorChildKey:childKey]; + } else { + FNamedNode *node = [self.indexed + predecessorEntry:[FNamedNode nodeWithName:childKey node:childNode]]; + return node.name; + } +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + [self.node enumerateChildrenReverse:reverse usingBlock:block]; + } else { + [self.indexed + enumerateObjectsReverse:reverse + usingBlock:^(FNamedNode *namedNode, BOOL *stop) { + block(namedNode.name, namedNode.node, stop); + }]; + } +} + +- (NSEnumerator *)childEnumerator { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node childEnumerator]; + } else { + return [self.indexed objectEnumerator]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h new file mode 100644 index 00000000..6bd2862a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FLeafNode : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue withPriority:(id)aPriority; + +@property(nonatomic, strong) id value; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m new file mode 100644 index 00000000..e741fd93 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLeafNode.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FImmutableSortedDictionary.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" + +@interface FLeafNode () +@property(nonatomic, strong) id priorityNode; +@property(nonatomic, strong) NSString *lazyHash; + +@end + +@implementation FLeafNode + +@synthesize value; +@synthesize priorityNode; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.priorityNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)initWithValue:(id)aValue withPriority:(id)aPriority { + self = [super init]; + if (self) { + self.value = aValue; + [FSnapshotUtilities validatePriorityNode:aPriority]; + self.priorityNode = aPriority; + } + return self; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return YES; +} + +- (id)getPriority { + return self.priorityNode; +} + +- (id)updatePriority:(id)aPriority { + return [[FLeafNode alloc] initWithValue:self.value withPriority:aPriority]; +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)getChild:(FPath *)path { + if (path.getFront == nil) { + return self; + } else if ([[path getFront] isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return + [childName isEqualToString:@".priority"] && ![self getPriority].isEmpty; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return nil; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else if (newChildNode.isEmpty) { + return self; + } else { + FChildrenNode *childrenNode = [[FChildrenNode alloc] init]; + childrenNode = [childrenNode updateImmediateChild:childName + withNewChild:newChildNode]; + childrenNode = [childrenNode updatePriority:self.priorityNode]; + return childrenNode; + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else if (newChildNode.isEmpty && ![front isEqualToString:@".priority"]) { + return self; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + return [self updateImmediateChild:front + withNewChild:[[FEmptyNode emptyNode] + updateChild:[path popFront] + withNewChild:newChildNode]]; + } +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if (exp && !self.getPriority.isEmpty) { + return @{ + kPayloadValue : self.value, + kPayloadPriority : [[self getPriority] val] + }; + } else { + return self.value; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other.isLeafNode) { + FLeafNode *otherLeaf = other; + if ([FUtilities getJavascriptType:self.value] != + [FUtilities getJavascriptType:otherLeaf.value]) { + return NO; + } + return [otherLeaf.value isEqual:self.value] && + [otherLeaf.priorityNode isEqual:self.priorityNode]; + } else { + return NO; + } +} + +- (NSUInteger)hash { + return [self.value hash] * 17 + self.priorityNode.hash; +} + +- (id)withIndex:(id)index { + return self; +} + +- (BOOL)isIndexed:(id)index { + return YES; +} + +- (BOOL)isEmpty { + return NO; +} + +- (int)numChildren { + return 0; +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + // Nothing to iterate over +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + // Nothing to iterate over +} + +- (NSEnumerator *)childEnumerator { + // Nothing to iterate over + return [@[] objectEnumerator]; +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:self + toString:toHash + hashVersion:FDataHashVersionV1]; + + self.lazyHash = [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + if (other == [FEmptyNode emptyNode]) { + return NSOrderedDescending; + } else if ([other isKindOfClass:[FChildrenNode class]]) { + return NSOrderedAscending; + } else { + NSAssert(other.isLeafNode, @"Compared against unknown type of node."); + return [self compareToLeafNode:(FLeafNode *)other]; + } +} + ++ (NSArray *)valueTypeOrder { + static NSArray *valueOrder = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueOrder = @[ + kJavaScriptObject, kJavaScriptBoolean, kJavaScriptNumber, + kJavaScriptString + ]; + }); + return valueOrder; +} + +- (NSComparisonResult)compareToLeafNode:(FLeafNode *)other { + NSString *thisLeafType = [FUtilities getJavascriptType:self.value]; + NSString *otherLeafType = [FUtilities getJavascriptType:other.value]; + NSUInteger thisIndex = + [[FLeafNode valueTypeOrder] indexOfObject:thisLeafType]; + NSUInteger otherIndex = + [[FLeafNode valueTypeOrder] indexOfObject:otherLeafType]; + assert(thisIndex >= 0 && otherIndex >= 0); + if (otherIndex == thisIndex) { + // Same type. Compare values. + if (thisLeafType == kJavaScriptObject) { + // Deferred value nodes are all equal, but we should also never get + // to this point... + return NSOrderedSame; + } else if (thisLeafType == kJavaScriptString) { + return [self.value compare:other.value options:NSLiteralSearch]; + } else { + return [self.value compare:other.value]; + } + } else { + return thisIndex > otherIndex ? NSOrderedDescending + : NSOrderedAscending; + } +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +- (void)forEachChildDo:(fbt_bool_nsstring_node)action { + // There are no children, so there is nothing to do. + return; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h new file mode 100644 index 00000000..ea251b63 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@protocol FIndex; + +@protocol FNode + +- (BOOL)isLeafNode; +- (id)getPriority; +- (id)updatePriority:(id)priority; +- (id)getImmediateChild:(NSString *)childKey; +- (id)getChild:(FPath *)path; +- (NSString *)predecessorChildKey:(NSString *)childKey; +- (id)updateImmediateChild:(NSString *)childKey + withNewChild:(id)newChildNode; +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode; +- (BOOL)hasChild:(NSString *)childKey; +- (BOOL)isEmpty; +- (int)numChildren; +- (id)val; +- (id)valForExport:(BOOL)exp; +- (NSString *)dataHash; +- (NSComparisonResult)compare:(id)other; +- (BOOL)isEqual:(id)other; +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h new file mode 100644 index 00000000..bf446605 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@class FImmutableSortedDictionary; +@class FCompoundWrite; +@class FLeafNode; +@protocol FNode; + +typedef NS_ENUM(NSInteger, FDataHashVersion) { + FDataHashVersionV1, + FDataHashVersionV2, +}; + +@interface FSnapshotUtilities : NSObject + ++ (id)nodeFrom:(id)val; ++ (id)nodeFrom:(id)val priority:(id)priority; ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn; ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn; ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn; ++ (void)validatePriorityNode:(id)priorityNode; ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)val + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion; ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString; + ++ (NSUInteger)estimateSerializedNodeSize:(id)node; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m new file mode 100644 index 00000000..f3f9ed59 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m @@ -0,0 +1,394 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotUtilities.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FUtilities.h" +#import "FValidation.h" + +@implementation FSnapshotUtilities + ++ (id)nodeFrom:(id)val { + return [FSnapshotUtilities nodeFrom:val priority:nil]; +} + ++ (id)nodeFrom:(id)val priority:(id)priority { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:@"nodeFrom:priority:"]; +} + ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val priority:nil withValidationFrom:fn]; +} + ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:fn + atDepth:0 + path:[[NSMutableArray alloc] init]]; +} + ++ (id)nodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + @autoreleasepool { + return [FSnapshotUtilities internalNodeFrom:val + priority:aPriority + withValidationFrom:fn + atDepth:depth + path:path]; + } +} + ++ (id)internalNodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + + if (depth > kFirebaseMaxObjectDepth) { + NSRange range; + range.location = 0; + range.length = 100; + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Max object depth exceeded: %@...", + fn, pathString] + userInfo:nil]; + } + + if (val == nil || val == [NSNull null]) { + // Null is a valid type to store + return [FEmptyNode emptyNode]; + } + + [FValidation validateFrom:fn isValidPriorityValue:aPriority withPath:path]; + id priority = [FSnapshotUtilities nodeFrom:aPriority]; + + id value = val; + BOOL isLeafNode = NO; + + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = val; + if (dict[kPayloadPriority] != nil) { + id rawPriority = [dict objectForKey:kPayloadPriority]; + [FValidation validateFrom:fn + isValidPriorityValue:rawPriority + withPath:path]; + priority = [FSnapshotUtilities nodeFrom:rawPriority]; + } + + if (dict[kPayloadValue] != nil) { + value = [dict objectForKey:kPayloadValue]; + if ([FValidation validateFrom:fn + isValidLeafValue:value + withPath:path]) { + isLeafNode = YES; + } else { + @throw [[NSException alloc] + initWithName:@"InvalidLeafValueType" + reason:[NSString stringWithFormat: + @"(%@) Invalid data type used " + @"with .value. Can only use " + "NSString and NSNumber or be " + "null. Found %@ instead.", + fn, [[value class] description]] + userInfo:nil]; + } + } + } + + if ([FValidation validateFrom:fn isValidLeafValue:value withPath:path]) { + isLeafNode = YES; + } + + if (isLeafNode) { + return [[FLeafNode alloc] initWithValue:value withPriority:priority]; + } + + // Unlike with JS, we have to handle the dictionary and array cases + // separately. + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = (NSDictionary *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:dval.count]; + + // Avoid creating a million newPaths by appending to old one + for (id keyId in dval) { + [FValidation validateFrom:fn + validDictionaryKey:keyId + withPath:path]; + NSString *key = (NSString *)keyId; + + if (![key hasPrefix:kPayloadMetadataPrefix]) { + [path addObject:key]; + id childNode = [FSnapshotUtilities nodeFrom:dval[key] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *aval = (NSArray *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:aval.count]; + + for (int i = 0; i < [aval count]; i++) { + NSString *key = [NSString stringWithFormat:@"%i", i]; + [path addObject:key]; + id childNode = + [FSnapshotUtilities nodeFrom:[aval objectAtIndex:i] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store object of type %@ at %@. " + "Can only store objects of type NSNumber, " + "NSString, NSDictionary, and NSArray.", + fn, [[value class] description], pathString] + userInfo:nil]; + } +} + ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn { + FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + + NSMutableArray *updatePaths = + [NSMutableArray arrayWithCapacity:values.count]; + for (NSString *keyId in values) { + id value = values[keyId]; + [FValidation validateFrom:fn + validUpdateDictionaryKey:keyId + withValue:value]; + + FPath *path = [FPath pathWithString:keyId]; + id node = [FSnapshotUtilities nodeFrom:value + withValidationFrom:fn]; + + [updatePaths addObject:path]; + compoundWrite = [compoundWrite addWrite:node atPath:path]; + } + + // Check that the update paths are not descendants of each other. + [updatePaths + sortUsingComparator:^NSComparisonResult(FPath *left, FPath *right) { + return [left compare:right]; + }]; + FPath *prevPath = nil; + for (FPath *path in updatePaths) { + if (prevPath != nil && [prevPath contains:path]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid path in object. Path " + @"(%@) is an ancestor of (%@).", + fn, prevPath, path] + userInfo:nil]; + } + prevPath = path; + } + + return compoundWrite; +} + ++ (void)validatePriorityNode:(id)priorityNode { + assert(priorityNode != nil); + if (priorityNode.isLeafNode) { + id val = priorityNode.val; + if ([val isKindOfClass:[NSDictionary class]]) { + NSDictionary *valDict __unused = (NSDictionary *)val; + NSAssert(valDict[kServerValueSubKey] != nil, + @"Priority can't be object unless it's a deferred value"); + } else { + NSString *jsType __unused = [FUtilities getJavascriptType:val]; + NSAssert(jsType == kJavaScriptString || jsType == kJavaScriptNumber, + @"Priority of unexpected type."); + } + } else { + NSAssert(priorityNode == [FMaxNode maxNode] || priorityNode.isEmpty, + @"Priority of unexpected type."); + } + // Don't call getPriority() on MAX_NODE to avoid hitting assertion. + NSAssert(priorityNode == [FMaxNode maxNode] || + priorityNode.getPriority.isEmpty, + @"Priority nodes can't have a priority of their own."); +} + ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)leafNode + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion { + NSAssert(hashVersion == FDataHashVersionV1 || + hashVersion == FDataHashVersionV2, + @"Unknown hash version: %lu", (unsigned long)hashVersion); + if (!leafNode.getPriority.isEmpty) { + [string appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode.getPriority + toString:string + hashVersion:hashVersion]; + [string appendString:@":"]; + } + + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + [string appendString:jsType]; + [string appendString:@":"]; + + if (jsType == kJavaScriptBoolean) { + NSString *boolString = + [leafNode.val boolValue] ? kJavaScriptTrue : kJavaScriptFalse; + [string appendString:boolString]; + } else if (jsType == kJavaScriptNumber) { + NSString *numberString = + [FUtilities ieee754StringForNumber:leafNode.val]; + [string appendString:numberString]; + } else if (jsType == kJavaScriptString) { + if (hashVersion == FDataHashVersionV1) { + [string appendString:leafNode.val]; + } else { + NSAssert(hashVersion == FDataHashVersionV2, + @"Invalid hash version found"); + [FSnapshotUtilities appendHashV2RepresentationForString:leafNode.val + toString:string]; + } + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown value for hashing: %@", leafNode]; + } +} + ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString { + string = [string stringByReplacingOccurrencesOfString:@"\\" + withString:@"\\\\"]; + string = [string stringByReplacingOccurrencesOfString:@"\"" + withString:@"\\\""]; + [mutableString appendString:@"\""]; + [mutableString appendString:string]; + [mutableString appendString:@"\""]; +} + ++ (NSUInteger)estimateLeafNodeSize:(FLeafNode *)leafNode { + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + // These values are somewhat arbitrary, but we don't need an exact value so + // prefer performance over exact value + NSUInteger valueSize; + if (jsType == kJavaScriptNumber) { + valueSize = 8; // estimate each float with 8 bytes + } else if (jsType == kJavaScriptBoolean) { + valueSize = 4; // true or false need roughly 4 bytes + } else if (jsType == kJavaScriptString) { + valueSize = 2 + [leafNode.val length]; // add 2 for quotes + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown leaf type: %@", leafNode]; + return 0; + } + + if (leafNode.getPriority.isEmpty) { + return valueSize; + } else { + // Account for extra overhead due to the extra JSON object and the + // ".value" and ".priority" keys, colons, comma + NSUInteger leafPriorityOverhead = 2 + 8 + 11 + 2 + 1; + return leafPriorityOverhead + valueSize + + [FSnapshotUtilities estimateLeafNodeSize:leafNode.getPriority]; + } +} + ++ (NSUInteger)estimateSerializedNodeSize:(id)node { + if ([node isEmpty]) { + return 4; // null keyword + } else if ([node isLeafNode]) { + return [FSnapshotUtilities estimateLeafNodeSize:node]; + } else { + NSAssert([node isKindOfClass:[FChildrenNode class]], + @"Unexpected node type: %@", [node class]); + __block NSUInteger sum = 1; // opening brackets + [((FChildrenNode *)node) enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id child, + BOOL *stop) { + sum += key.length; + sum += + 4; // quotes around key and colon and (comma or closing bracket) + sum += [FSnapshotUtilities estimateSerializedNodeSize:child]; + }]; + return sum; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h new file mode 100644 index 00000000..b8668d2e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FAtomicNumber : NSObject + +- (NSNumber *)getAndIncrement; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m new file mode 100644 index 00000000..20cfd8df --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAtomicNumber.h" + +@interface FAtomicNumber () { + unsigned long number; +} + +@property(nonatomic, strong) NSLock *lock; + +@end + +@implementation FAtomicNumber + +@synthesize lock; + +- (id)init { + self = [super init]; + if (self) { + number = 1; + self.lock = [[NSLock alloc] init]; + } + return self; +} + +- (NSNumber *)getAndIncrement { + NSNumber *result; + + // See: + // http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW14 + // to improve, etc. + + [self.lock lock]; + result = [NSNumber numberWithUnsignedLong:number]; + number = number + 1; + [self.lock unlock]; + + return result; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h new file mode 100644 index 00000000..fc19ca75 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseQuery.h" +#import "FTypedefs_Private.h" + +@interface FEventEmitter : NSObject + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue; + +- (id)getInitialEventForType:(NSString *)eventType; +- (void)triggerEventType:(NSString *)eventType data:(id)data; + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block; +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle; + +- (void)validateEventType:(NSString *)eventType; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m new file mode 100644 index 00000000..7d02239c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m @@ -0,0 +1,161 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventEmitter.h" +#import "FIRDatabaseQuery_Private.h" +#import "FRepoManager.h" +#import "FUtilities.h" + +@interface FEventListener : NSObject + +@property(nonatomic, copy) fbt_void_id userCallback; +@property(nonatomic) FIRDatabaseHandle handle; + +@end + +@implementation FEventListener + +@synthesize userCallback; +@synthesize handle; + +@end + +@interface FEventEmitter () + +@property(nonatomic, strong) NSArray *allowedEvents; +@property(nonatomic, strong) NSMutableDictionary *listeners; +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +@implementation FEventEmitter + +@synthesize allowedEvents; +@synthesize listeners; + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue { + if (theAllowedEvents == nil || [theAllowedEvents count] == 0) { + @throw [NSException + exceptionWithName:@"AllowedEventsValidation" + reason:@"FEventEmitters must be initialized with at " + @"least one valid event." + userInfo:nil]; + } + + self = [super init]; + + if (self) { + self.allowedEvents = [theAllowedEvents copy]; + self.listeners = [[NSMutableDictionary alloc] init]; + self.queue = queue; + } + + return self; +} + +- (id)getInitialEventForType:(NSString *)eventType { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"You must override getInitialEvent: " + @"when subclassing FEventEmitter" + userInfo:nil]; +} + +- (void)triggerEventType:(NSString *)eventType data:(id)data { + [self validateEventType:eventType]; + NSMutableDictionary *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in eventTypeListeners) { + [self triggerListener:listener withData:data]; + } +} + +- (void)triggerListener:(FEventListener *)listener withData:(id)data { + // TODO, should probably get this from FRepo or something although it ends + // up being the same. (Except maybe for testing) + if (listener.userCallback) { + dispatch_async(self.queue, ^{ + listener.userCallback(data); + }); + } +} + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block { + [self validateEventType:eventType]; + + // Create listener + FEventListener *listener = [[FEventListener alloc] init]; + listener.handle = [[FUtilities LUIDGenerator] integerValue]; + listener.userCallback = block; // copies block automatically + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self addEventListener:listener forEventType:eventType]; + }); + + return listener.handle; +} + +- (void)addEventListener:(FEventListener *)listener + forEventType:(NSString *)eventType { + // Get or initializer listeners map [FIRDatabaseHandle -> callback block] + // for eventType + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + if (eventTypeListeners == nil) { + eventTypeListeners = [[NSMutableArray alloc] init]; + [self.listeners setObject:eventTypeListeners forKey:eventType]; + } + + // Add listener and fire the current event for this listener + [eventTypeListeners addObject:listener]; + id initialData = [self getInitialEventForType:eventType]; + [self triggerListener:listener withData:initialData]; +} + +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle { + [self validateEventType:eventType]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self removeEventListenerWithHandle:handle forEventType:eventType]; + }); +} + +- (void)removeEventListenerWithHandle:(FIRDatabaseHandle)handle + forEventType:(NSString *)eventType { + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in [eventTypeListeners copy]) { + if (handle == NSNotFound || handle == listener.handle) { + [eventTypeListeners removeObject:listener]; + } + } +} + +- (void)validateEventType:(NSString *)eventType { + if ([self.allowedEvents indexOfObject:eventType] == NSNotFound) { + @throw [NSException + exceptionWithName:@"InvalidEventType" + reason:[NSString stringWithFormat: + @"%@ is not a valid event type. %@ " + @"is the list of valid events.", + eventType, self.allowedEvents] + userInfo:nil]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h new file mode 100644 index 00000000..5a661960 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FNextPushId : NSObject + ++ (NSString *)get:(NSTimeInterval)now; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m new file mode 100644 index 00000000..864e1474 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNextPushId.h" +#import "FUtilities.h" + +static NSString *const PUSH_CHARS = + @"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; + +@implementation FNextPushId + ++ (NSString *)get:(NSTimeInterval)currentTime { + static long long lastPushTime = 0; + static int lastRandChars[12]; + + long long now = (long long)(currentTime * 1000); + + BOOL duplicateTime = now == lastPushTime; + lastPushTime = now; + + unichar timeStampChars[8]; + for (int i = 7; i >= 0; i--) { + timeStampChars[i] = [PUSH_CHARS characterAtIndex:(now % 64)]; + now = (long long)floor(now / 64); + } + + NSMutableString *id = [[NSMutableString alloc] init]; + [id appendString:[NSString stringWithCharacters:timeStampChars length:8]]; + + if (!duplicateTime) { + for (int i = 0; i < 12; i++) { + lastRandChars[i] = (int)floor(arc4random() % 64); + } + } else { + int i = 0; + for (i = 11; i >= 0 && lastRandChars[i] == 63; i--) { + lastRandChars[i] = 0; + } + lastRandChars[i]++; + } + + for (int i = 0; i < 12; i++) { + [id appendFormat:@"%C", [PUSH_CHARS characterAtIndex:lastRandChars[i]]]; + } + + return [NSString stringWithString:id]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h new file mode 100644 index 00000000..1c072845 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FRepoInfo.h" + +@interface FParsedUrl : NSObject + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPath *path; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m new file mode 100644 index 00000000..eb833309 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FParsedUrl.h" + +@implementation FParsedUrl + +@synthesize repoInfo; +@synthesize path; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h new file mode 100644 index 00000000..f7d19b6e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FStringUtilities : NSObject + ++ (NSString *)base64EncodedSha1:(NSString *)str; ++ (NSString *)urlDecoded:(NSString *)url; ++ (NSString *)urlEncoded:(NSString *)url; ++ (NSString *)sanitizedForUserAgent:(NSString *)str; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m new file mode 100644 index 00000000..2515257b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FStringUtilities.h" +#import "NSData+SRB64Additions.h" +#import + +@implementation FStringUtilities + +// http://stackoverflow.com/questions/3468268/objective-c-sha1 +// http://stackoverflow.com/questions/7310457/ios-objective-c-sha-1-and-base64-problem ++ (NSString *)base64EncodedSha1:(NSString *)str { + const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding]; + // NSString reports length in characters, but we want it in bytes, which + // strlen will give us. + unsigned long dataLen = strlen(cstr); + NSData *data = [NSData dataWithBytes:cstr length:dataLen]; + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes, (unsigned int)data.length, digest); + NSData *output = [[NSData alloc] initWithBytes:digest + length:CC_SHA1_DIGEST_LENGTH]; + return [FSRUtilities base64EncodedStringFromData:output]; +} + ++ (NSString *)urlDecoded:(NSString *)url { + NSString *replaced = [url stringByReplacingOccurrencesOfString:@"+" + withString:@" "]; + NSString *decoded = [replaced stringByRemovingPercentEncoding]; + // This is kind of a hack, but is generally how the js client works. We + // could run into trouble if some piece is a correctly escaped %-sequence, + // and another isn't. But, that's bad input anyways... + if (decoded) { + return decoded; + } else { + return replaced; + } +} + ++ (NSString *)urlEncoded:(NSString *)url { + // Didn't seem like there was an Apple NSCharacterSet that had our version + // of the encoding So I made my own, following RFC 2396 + // https://www.ietf.org/rfc/rfc2396.txt allowedCharacters = alphanum | "-" | + // "_" | "~" + NSCharacterSet *allowedCharacters = [NSCharacterSet + characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGH" + @"IJKLMNOPQRSTUVWXYZ0123456789-_~"]; + return [url + stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; +} + ++ (NSString *)sanitizedForUserAgent:(NSString *)str { + return + [str stringByReplacingOccurrencesOfString:@"/|_" + withString:@"|" + options:NSRegularExpressionSearch + range:NSMakeRange(0, [str length])]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h new file mode 100644 index 00000000..56d97fff --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef Firebase_FTypedefs_h +#define Firebase_FTypedefs_h + +/** + * Stub... + */ +@class FIRDataSnapshot; +@class FIRDatabaseReference; +@class FAuthData; +@protocol FNode; + +// fbt = Firebase Block Typedef + +typedef void (^fbt_void_void)(void); +typedef void (^fbt_void_datasnapshot_nsstring)(FIRDataSnapshot *snapshot, + NSString *prevName); +typedef void (^fbt_void_datasnapshot)(FIRDataSnapshot *snapshot); +typedef void (^fbt_void_user)(FAuthData *user); +typedef void (^fbt_void_nsstring_id)(NSString *status, id data); +typedef void (^fbt_void_nserror_id)(NSError *error, id data); +typedef void (^fbt_void_nserror)(NSError *error); +typedef void (^fbt_void_nserror_ref)(NSError *error, FIRDatabaseReference *ref); +typedef void (^fbt_void_nserror_user)(NSError *error, FAuthData *user); +typedef void (^fbt_void_nserror_json)(NSError *error, NSDictionary *json); +typedef void (^fbt_void_nsdictionary)(NSDictionary *data); +typedef id (^fbt_id_node_nsstring)(id node, NSString *childName); + +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h new file mode 100644 index 00000000..3a1ca3c1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import + +#import "FParsedUrl.h" + +@interface FUtilities : NSObject + ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size; ++ (NSNumber *)LUIDGenerator; ++ (FParsedUrl *)parseUrl:(NSString *)url; ++ (NSString *)getJavascriptType:(id)obj; ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason; ++ (NSNumber *)intForString:(NSString *)string; ++ (NSString *)ieee754StringForNumber:(NSNumber *)val; ++ (void)setLoggingEnabled:(BOOL)enabled; ++ (BOOL)getLoggingEnabled; + ++ (NSString *)minName; ++ (NSString *)maxName; ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b; ++ (NSComparator)stringComparator; ++ (NSComparator)keyComparator; + ++ (double)randomDouble; + +@end + +typedef enum { + FLogLevelDebug = 1, + FLogLevelInfo = 2, + FLogLevelWarn = 3, + FLogLevelError = 4, + FLogLevelNone = 5 +} FLogLevel; + +// Log tags +FOUNDATION_EXPORT NSString *const kFPersistenceLogTag; + +#define FFLog(code, format, ...) FFDebug((code), (format), ##__VA_ARGS__) + +#define FFDebug(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelDebug)) { \ + FIRLogDebug(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFInfo(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelInfo)) { \ + FIRLogError(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFWarn(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelWarn)) { \ + FIRLogWarning(kFIRLoggerDatabase, (code), (format), \ + ##__VA_ARGS__); \ + } \ + } while (0) + +extern FIRLoggerService kFIRLoggerDatabase; +BOOL FFIsLoggingEnabled(FLogLevel logLevel); +void firebaseUncaughtExceptionHandler(NSException *exception); +void firebaseJobsTroll(void); diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m new file mode 100644 index 00000000..df08a300 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m @@ -0,0 +1,433 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FUtilities.h" +#import "FAtomicNumber.h" +#import "FConstants.h" +#import "FStringUtilities.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#define ARC4RANDOM_MAX 0x100000000 +#define INTEGER_32_MIN (-2147483648) +#define INTEGER_32_MAX 2147483647 + +#pragma mark - +#pragma mark C functions + +FIRLoggerService kFIRLoggerDatabase = @"[Firebase/Database]"; +static FLogLevel logLevel = FLogLevelInfo; // Default log level is info +static NSMutableDictionary *options = nil; + +BOOL FFIsLoggingEnabled(FLogLevel level) { return level >= logLevel; } + +void firebaseJobsTroll(void) { + FFLog(@"I-RDB095001", + @"password super secret; JFK conspiracy; Hello there! Having fun " + @"digging through Firebase? We're always hiring! jobs@firebase.com"); +} + +#pragma mark - +#pragma mark Private property and singleton specification + +@interface FUtilities () { +} + +@property(nonatomic, strong) FAtomicNumber *localUid; + ++ (FUtilities *)singleton; + +@end + +@implementation FUtilities + +@synthesize localUid; + +- (id)init { + self = [super init]; + if (self) { + self.localUid = [[FAtomicNumber alloc] init]; + } + return self; +} + +// TODO: We really want to be able to set the log level ++ (void)setLoggingEnabled:(BOOL)enabled { + logLevel = enabled ? FLogLevelDebug : FLogLevelInfo; +} + ++ (BOOL)getLoggingEnabled { + return logLevel == FLogLevelDebug; +} + ++ (FUtilities *)singleton { + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +// Refactor as a category of NSString ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size { + if (str.length <= size) { + return [NSArray arrayWithObject:str]; + } + + NSMutableArray *dataSegs = [[NSMutableArray alloc] init]; + for (int c = 0; c < str.length; c += size) { + if (c + size > str.length) { + int rangeStart = c; + unsigned long rangeLength = size - ((c + size) - str.length); + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } else { + int rangeStart = c; + int rangeLength = size; + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } + } + return dataSegs; +} + ++ (NSNumber *)LUIDGenerator { + FUtilities *f = [FUtilities singleton]; + return [f.localUid getAndIncrement]; +} + ++ (NSString *)decodePath:(NSString *)pathString { + NSMutableArray *decodedPieces = [[NSMutableArray alloc] init]; + NSArray *pieces = [pathString componentsSeparatedByString:@"/"]; + for (NSString *piece in pieces) { + if (piece.length > 0) { + [decodedPieces addObject:[FStringUtilities urlDecoded:piece]]; + } + } + return [NSString + stringWithFormat:@"/%@", [decodedPieces componentsJoinedByString:@"/"]]; +} + ++ (NSString *)extractPathFromUrlString:(NSString *)url { + NSString *path = url; + + NSRange schemeIndex = [path rangeOfString:@"//"]; + if (schemeIndex.location != NSNotFound) { + path = [path substringFromIndex:schemeIndex.location + 2]; + } + + NSUInteger pathIndex = [path rangeOfString:@"/"].location; + if (pathIndex != NSNotFound) { + path = [path substringFromIndex:pathIndex + 1]; + } else { + path = @""; + } + + NSUInteger queryParamIndex = [path rangeOfString:@"?"].location; + if (queryParamIndex != NSNotFound) { + path = [path substringToIndex:queryParamIndex]; + } + + return path; +} + ++ (FParsedUrl *)parseUrl:(NSString *)url { + // For backwards compatibility, support URLs without schemes on iOS. + if (![url containsString:@"://"]) { + url = [@"http://" stringByAppendingString:url]; + } + + NSString *originalPathString = [self extractPathFromUrlString:url]; + + // Sanitize the database URL by removing the path component, which may + // contain invalid URL characters. + NSString *sanitizedUrlWithoutPath = + [url stringByReplacingOccurrencesOfString:originalPathString + withString:@""]; + NSURLComponents *urlComponents = + [NSURLComponents componentsWithString:sanitizedUrlWithoutPath]; + if (!urlComponents) { + [NSException raise:@"Failed to parse database URL" + format:@"Failed to parse database URL: %@", url]; + } + + NSString *host = [urlComponents.host lowercaseString]; + NSString *namespace; + bool secure; + + if (urlComponents.port != nil) { + secure = [urlComponents.scheme isEqualToString:@"https"] || + [urlComponents.scheme isEqualToString:@"wss"]; + host = [host stringByAppendingFormat:@":%@", urlComponents.port]; + } else { + secure = YES; + }; + + NSArray *parts = [urlComponents.host componentsSeparatedByString:@"."]; + if ([parts count] == 3) { + namespace = [parts[0] lowercaseString]; + } else { + // Attempt to extract namespace from "ns" query param. + NSArray *queryItems = urlComponents.queryItems; + for (NSURLQueryItem *item in queryItems) { + if ([item.name isEqualToString:@"ns"]) { + namespace = item.value; + break; + } + } + + if (!namespace) { + namespace = [parts[0] lowercaseString]; + } + } + + NSString *pathString = [self + decodePath:[NSString stringWithFormat:@"/%@", originalPathString]]; + FPath *path = [[FPath alloc] initWith:pathString]; + FRepoInfo *repoInfo = [[FRepoInfo alloc] initWithHost:host + isSecure:secure + withNamespace:namespace]; + + FFLog(@"I-RDB095002", @"---> Parsed (%@) to: (%@,%@); ns=(%@); path=(%@)", + url, [repoInfo description], [repoInfo connectionURL], + repoInfo.namespace, [path description]); + + FParsedUrl *parsedUrl = [[FParsedUrl alloc] init]; + parsedUrl.repoInfo = repoInfo; + parsedUrl.path = path; + + return parsedUrl; +} + +/* + case str: JString => priString + "string:" + str.s; + case bool: JBool => priString + "boolean:" + bool.value; + case double: JDouble => priString + "number:" + double.num; + case int: JInt => priString + "number:" + int.num; + case _ => { + error("Leaf node has value '" + data.value + "' of invalid type '" + + data.value.getClass.toString + "'"); + ""; + } + */ + ++ (NSString *)getJavascriptType:(id)obj { + if ([obj isKindOfClass:[NSDictionary class]]) { + return kJavaScriptObject; + } else if ([obj isKindOfClass:[NSString class]]) { + return kJavaScriptString; + } else if ([obj isKindOfClass:[NSNumber class]]) { + // We used to just compare to @encode(BOOL) as suggested at + // http://stackoverflow.com/questions/2518761/get-type-of-nsnumber, but + // on arm64, @encode(BOOL) returns "B" instead of "c" even though + // objCType still returns 'c' (signed char). So check both. + if (strcmp([obj objCType], @encode(BOOL)) == 0 || + strcmp([obj objCType], @encode(signed char)) == 0) { + return kJavaScriptBoolean; + } else { + return kJavaScriptNumber; + } + } else { + return kJavaScriptNull; + } +} + ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason { + static dispatch_once_t pred = 0; + __strong static NSDictionary *errorMap = nil; + __strong static NSDictionary *errorCodes = nil; + dispatch_once(&pred, ^{ + errorMap = @{ + @"permission_denied" : @"Permission Denied", + @"unavailable" : @"Service is unavailable", + kFErrorWriteCanceled : @"Write cancelled by user" + }; + errorCodes = @{ + @"permission_denied" : @1, + @"unavailable" : @2, + kFErrorWriteCanceled : @3 + }; + }); + + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + return nil; + } else { + NSInteger code; + NSString *desc = nil; + if (reason) { + desc = reason; + } else if ([errorMap objectForKey:status] != nil) { + desc = [errorMap objectForKey:status]; + } else { + desc = status; + } + + if ([errorCodes objectForKey:status] != nil) { + NSNumber *num = [errorCodes objectForKey:status]; + code = [num integerValue]; + } else { + // XXX what to do here? + code = 9999; + } + + return [[NSError alloc] + initWithDomain:kFErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : desc}]; + } +} + ++ (NSNumber *)intForString:(NSString *)string { + static NSCharacterSet *notDigits = nil; + if (!notDigits) { + notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + } + if ([string rangeOfCharacterFromSet:notDigits].length == 0) { + NSInteger num; + NSScanner *scanner = [NSScanner scannerWithString:string]; + if ([scanner scanInteger:&num]) { + return [NSNumber numberWithInteger:num]; + } + } + return nil; +} + ++ (NSString *)ieee754StringForNumber:(NSNumber *)val { + double d = [val doubleValue]; + NSData *data = [NSData dataWithBytes:&d length:sizeof(double)]; + NSMutableString *str = [[NSMutableString alloc] init]; + const unsigned char *buffer = (const unsigned char *)[data bytes]; + for (int i = 0; i < data.length; i++) { + unsigned char byte = buffer[7 - i]; + [str appendFormat:@"%02x", byte]; + } + return str; +} + +static inline BOOL tryParseStringToInt(__unsafe_unretained NSString *str, + NSInteger *integer) { + // First do some cheap checks (NOTE: The below checks are significantly + // faster than an equivalent regex :-( ). + NSUInteger length = str.length; + if (length > 11 || length == 0) { + return NO; + } + long long value = 0; + BOOL negative = NO; + NSUInteger i = 0; + if ([str characterAtIndex:0] == '-') { + if (length == 1) { + return NO; + } + negative = YES; + i = 1; + } + for (; i < length; i++) { + unichar c = [str characterAtIndex:i]; + // Must be a digit, or '-' if it's the first char. + if (c < '0' || c > '9') { + return NO; + } else { + int charValue = c - '0'; + value = value * 10 + charValue; + } + } + + value = (negative) ? -value : value; + + if (value < INTEGER_32_MIN || value > INTEGER_32_MAX) { + return NO; + } else { + *integer = (NSInteger)value; + return YES; + } +} + ++ (NSString *)maxName { + static dispatch_once_t once; + static NSString *maxName; + dispatch_once(&once, ^{ + maxName = [[NSString alloc] initWithFormat:@"[MAX_NAME]"]; + }); + return maxName; +} + ++ (NSString *)minName { + static dispatch_once_t once; + static NSString *minName; + dispatch_once(&once, ^{ + minName = [[NSString alloc] initWithFormat:@"[MIN_NAME]"]; + }); + return minName; +} + ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b { + if (a == b) { + return NSOrderedSame; + } else if (a == [FUtilities minName] || b == [FUtilities maxName]) { + return NSOrderedAscending; + } else if (b == [FUtilities minName] || a == [FUtilities maxName]) { + return NSOrderedDescending; + } else { + NSInteger aAsInt, bAsInt; + if (tryParseStringToInt(a, &aAsInt)) { + if (tryParseStringToInt(b, &bAsInt)) { + if (aAsInt > bAsInt) { + return NSOrderedDescending; + } else if (aAsInt < bAsInt) { + return NSOrderedAscending; + } else if (a.length > b.length) { + return NSOrderedDescending; + } else if (a.length < b.length) { + return NSOrderedAscending; + } else { + return NSOrderedSame; + } + } else { + return (NSComparisonResult)NSOrderedAscending; + } + } else if (tryParseStringToInt(b, &bAsInt)) { + return (NSComparisonResult)NSOrderedDescending; + } else { + // Perform literal character by character search to prevent a > b && + // b > a issues. Note that calling -(NSString + // *)decomposedStringWithCanonicalMapping also works. + return [a compare:b options:NSLiteralSearch]; + } + } +} + ++ (NSComparator)keyComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [FUtilities compareKey:a toKey:b]; + }; +} + ++ (NSComparator)stringComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [a compare:b]; + }; +} + ++ (double)randomDouble { + return ((double)arc4random() / ARC4RANDOM_MAX); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h new file mode 100644 index 00000000..276eb267 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FParsedUrl.h" +#import "FPath.h" +#import "FTypedefs.h" +#import + +@interface FValidation : NSObject + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path; ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event; ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key; ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl; + ++ (void)validateToken:(NSString *)token; + +// Functions for handling passing errors back ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback; ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback; + +// Functions used for validating while creating snapshots in FSnapshotUtilities ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value; ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path; ++ (BOOL)validatePriorityValue:value; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m new file mode 100644 index 00000000..c700b9ce --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m @@ -0,0 +1,461 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValidation.h" +#import "FConstants.h" +#import "FParsedUrl.h" +#import "FTypedefs.h" + +// Have to escape: * ? + [ ( ) { } ^ $ | \ . / +// See: +// https://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html + +NSString *const kInvalidPathCharacters = @"[].#$"; +NSString *const kInvalidKeyCharacters = @"[].#$/"; + +@implementation FValidation + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path { + if ([[path getFront] isEqualToString:kDotInfoPrefix]) { + @throw [[NSException alloc] + initWithName:@"WritablePathValidation" + reason:[NSString + stringWithFormat:@"(%@) failed to path %@: Can't " + @"modify data under %@", + fn, [path description], + kDotInfoPrefix] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event { + switch (event) { + case FIRDataEventTypeValue: + case FIRDataEventTypeChildAdded: + case FIRDataEventTypeChildChanged: + case FIRDataEventTypeChildMoved: + case FIRDataEventTypeChildRemoved: + return; + break; + default: + @throw [[NSException alloc] + initWithName:@"KnownEventTypeValidation" + reason:[NSString + stringWithFormat:@"(%@) Unknown event type: %d", + fn, (int)event] + userInfo:nil]; + break; + } +} + ++ (BOOL)isValidPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSCharacterSet *badPathChars = nil; + dispatch_once(&token, ^{ + badPathChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidPathCharacters]; + }); + return pathString != nil && [pathString length] != 0 && + [pathString rangeOfCharacterFromSet:badPathChars].location == + NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString { + if (![self isValidPathString:pathString]) { + @throw [[NSException alloc] + initWithName:@"InvalidPathValidation" + reason:[NSString stringWithFormat: + @"(%@) Must be a non-empty string and " + @"not contain '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSRegularExpression *dotInfoRegex = nil; + dispatch_once(&token, ^{ + dotInfoRegex = [NSRegularExpression + regularExpressionWithPattern:@"^\\/*\\.info(\\/|$)" + options:0 + error:nil]; + }); + + NSString *tempPath = pathString; + // HACK: Obj-C regex are kinda' slow. Do a plain string search first before + // bothering with the regex. + if ([pathString rangeOfString:@".info"].location != NSNotFound) { + tempPath = [dotInfoRegex + stringByReplacingMatchesInString:pathString + options:0 + range:NSMakeRange(0, pathString.length) + withTemplate:@"/"]; + } + [self validateFrom:fn validPathString:tempPath]; +} + ++ (BOOL)isValidKey:(NSString *)key { + static dispatch_once_t token; + static NSCharacterSet *badKeyChars = nil; + dispatch_once(&token, ^{ + badKeyChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidKeyCharacters]; + }); + return key != nil && key.length > 0 && + [key rangeOfCharacterFromSet:badKeyChars].location == NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key { + if (![self isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidKeyValidation" + reason:[NSString + stringWithFormat: + @"(%@) Must be a non-empty string and not " + @"contain '/' '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl { + NSString *pathString = [parsedUrl.path description]; + [self validateFrom:fn validRootPathString:pathString]; +} + +#pragma mark - +#pragma mark Authentication validation + ++ (BOOL)stringNonempty:(NSString *)str { + return str != nil && ![str isKindOfClass:[NSNull class]] && str.length > 0; +} + ++ (void)validateToken:(NSString *)token { + if (![FValidation stringNonempty:token]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't have empty string or nil for custom token"]; + } +} + +#pragma mark - +#pragma mark Handling authentication errors + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback { + if (userCallback) { + userCallback(error, nil); + } +} + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback { + if (userCallback) { + userCallback(error); + } +} + +#pragma mark - +#pragma mark Snapshot validation + ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path { + if ([value isKindOfClass:[NSString class]]) { + // Try to avoid conversion to bytes if possible + NSString *theString = value; + if ([theString maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize && + [theString lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) String exceeds max " + @"size of %u utf8 bytes: %@", + fn, (int)kFirebaseMaxLeafSize, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSNumber class]]) { + // Cannot store NaN, but otherwise can store NSNumbers. + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store NaN at path: %@.", fn, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys.%@.", + fn, pathString] + userInfo:nil]; + } + return YES; + } + return NO; + } + + else if (value == [NSNull null] || value == nil) { + // Null is valid type to store at leaf + return YES; + } + + return NO; +} + ++ (NSString *)parseAndValidateKey:(id)keyId + fromFunction:(NSString *)fn + path:(NSArray *)path { + if (![keyId isKindOfClass:[NSString class]]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) Non-string keys are not " + @"allowed in object at path: %@", + fn, pathString] + userInfo:nil]; + } + return (NSString *)keyId; +} + ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path { + NSString *key = [self parseAndValidateKey:keyId fromFunction:fn path:path]; + if (![key isEqualToString:kPayloadPriority] && + ![key isEqualToString:kPayloadValue] && + ![key isEqualToString:kServerValueSubKey] && + ![FValidation isValidKey:key]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid key in object at path: " + @"%@. Keys must be non-empty and cannot " + @"contain '/' '.' '#' '$' '[' or ']'", + fn, pathString] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value { + FPath *path = [FPath pathWithString:[self parseAndValidateKey:keyId + fromFunction:fn + path:@[]]]; + __block NSInteger keyNum = 0; + [path enumerateComponentsUsingBlock:^void(NSString *key, BOOL *stop) { + if ([key isEqualToString:kPayloadPriority] && + keyNum == [path length] - 1) { + [self validateFrom:fn isValidPriorityValue:value withPath:@[]]; + } else { + keyNum++; + + if (![FValidation isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Invalid key in object. Keys must " + @"be non-empty and cannot contain '.' " + @"'#' '$' '[' or ']'", + fn] + userInfo:nil]; + } + } + }]; +} + ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path { + [self validateFrom:fn + isValidPriorityValue:value + withPath:path + throwError:YES]; +} + +/** + * Returns YES if priority is valid. + */ ++ (BOOL)validatePriorityValue:value { + return [self validateFrom:nil + isValidPriorityValue:value + withPath:nil + throwError:NO]; +} + +/** + * Helper for validating priorities. If passed YES for throwError, it'll throw + * descriptive errors on validation problems. Else, it'll just return YES/NO. + */ ++ (BOOL)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path + throwError:(BOOL)throwError { + if ([value isKindOfClass:[NSNumber class]]) { + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store NaN as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } else if (value == (id)kCFBooleanFalse || + value == (id)kCFBooleanTrue) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store true/false " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store an NSDictionary " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSArray class]]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store an NSArray as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + + // It's valid! + return YES; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h new file mode 100644 index 00000000..f5c08597 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import + +@interface FTupleBoolBlock : NSObject + +@property(nonatomic, readwrite) BOOL boolean; +@property(nonatomic, copy) fbt_void_void block; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m new file mode 100644 index 00000000..c4cd8bf2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleBoolBlock.h" + +@implementation FTupleBoolBlock + +@synthesize boolean; +@synthesize block; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h new file mode 100644 index 00000000..bd8c4a96 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleCallbackStatus : NSObject +@property(nonatomic, copy) fbt_void_nsstring_nsstring block; +@property(nonatomic) NSString *status; +@property(nonatomic) NSString *errorReason; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m new file mode 100644 index 00000000..05914bfd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleCallbackStatus.h" + +@implementation FTupleCallbackStatus +@synthesize block; +@synthesize status; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h new file mode 100644 index 00000000..5e41f9e3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@interface FTupleFirebase : NSObject + +@property(nonatomic, strong) FIRDatabaseReference *one; +@property(nonatomic, strong) FIRDatabaseReference *two; +@property(nonatomic, strong) FIRDatabaseReference *three; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m new file mode 100644 index 00000000..3956f8be --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleFirebase.h" + +@implementation FTupleFirebase + +@synthesize one; +@synthesize two; +@synthesize three; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h new file mode 100644 index 00000000..19b5217e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import + +@interface FTupleNodePath : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m new file mode 100644 index 00000000..620ae766 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleNodePath.h" + +@implementation FTupleNodePath + +@synthesize path; +@synthesize node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.path = aPath; + self.node = aNode; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h new file mode 100644 index 00000000..1717a220 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleObjectNode : NSObject + +- (id)initWithObject:(id)aObj andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) id obj; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m new file mode 100644 index 00000000..4c533b02 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "FTupleObjectNode.h" + +@implementation FTupleObjectNode + +@synthesize obj; +@synthesize node; + +- (id)initWithObject:(id)aObj andNode:(id)aNode { + self = [super init]; + if (self) { + self.obj = aObj; + self.node = aNode; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h new file mode 100644 index 00000000..05b31418 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleObjects : NSObject + +@property(nonatomic, strong) id objA; +@property(nonatomic, strong) id objB; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m new file mode 100644 index 00000000..a9e4c886 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleObjects.h" + +@implementation FTupleObjects + +@synthesize objA; +@synthesize objB; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h new file mode 100644 index 00000000..e68ab71b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleOnDisconnect : NSObject + +@property(strong, nonatomic) NSString *pathString; +@property(strong, nonatomic) NSString *action; +@property(strong, nonatomic) id data; +@property(strong, nonatomic) fbt_void_nsstring_nsstring onComplete; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m new file mode 100644 index 00000000..bd458220 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleOnDisconnect.h" + +@implementation FTupleOnDisconnect + +@synthesize pathString; +@synthesize action; +@synthesize data; +@synthesize onComplete; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h new file mode 100644 index 00000000..b0a515ce --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FTuplePathValue : NSObject +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id value; +- (id)initWithPath:(FPath *)aPath value:(id)aValue; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m new file mode 100644 index 00000000..91de8834 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTuplePathValue.h" +#import "FPath.h" + +@interface FTuplePathValue () +@property(nonatomic, strong, readwrite) id value; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FTuplePathValue +@synthesize path; +@synthesize value; + +- (id)initWithPath:(FPath *)aPath value:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.path = aPath; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h new file mode 100644 index 00000000..7269c2f1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleRemovedQueriesEvents : NSObject +/** + * `FIRDatabaseQuery`s removed with [SyncPoint removeEventRegistration:] + */ +@property(nonatomic, strong, readonly) NSArray *removedQueries; +/** + * cancel events as FEvent + */ +@property(nonatomic, strong, readonly) NSArray *cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events; +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m new file mode 100644 index 00000000..324cfcb2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleRemovedQueriesEvents.h" + +@interface FTupleRemovedQueriesEvents () +@property(nonatomic, strong, readwrite) NSArray *removedQueries; +@property(nonatomic, strong, readwrite) NSArray *cancelEvents; +@end + +@implementation FTupleRemovedQueriesEvents +@synthesize removedQueries; +@synthesize cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events { + self = [super init]; + if (self) { + self.removedQueries = removed; + self.cancelEvents = events; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h new file mode 100644 index 00000000..337f8d61 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +@interface FTupleSetIdPath : NSObject + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath; + +@property(strong, nonatomic) NSNumber *setId; +@property(strong, nonatomic) FPath *path; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m new file mode 100644 index 00000000..2763c83d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleSetIdPath.h" + +@implementation FTupleSetIdPath + +@synthesize path; +@synthesize setId; + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.setId = aSetId; + self.path = aPath; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h new file mode 100644 index 00000000..0e3d7fa4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleStringNode : NSObject + +- (id)initWithString:(NSString *)aString andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) NSString *string; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m new file mode 100644 index 00000000..d820ef80 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" + +@implementation FTupleStringNode + +@synthesize string; +@synthesize node; + +- (id)initWithString:(NSString *)aString andNode:(id)aNode { + self = [super init]; + if (self) { + self.string = aString; + self.node = aNode; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h new file mode 100644 index 00000000..b1052da3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" +#import + +@interface FTupleTSN : NSObject + +@property(nonatomic, strong) FTupleStringNode *from; +@property(nonatomic, strong) FTupleStringNode *to; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m new file mode 100644 index 00000000..348c3197 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTSN.h" + +@implementation FTupleTSN + +@synthesize from; +@synthesize to; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h new file mode 100644 index 00000000..82f44959 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@interface FTupleTransaction : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, copy) fbt_transactionresult_mutabledata update; +@property(nonatomic, copy) fbt_void_nserror_bool_datasnapshot onComplete; +@property(nonatomic) FTransactionStatus status; + +/** + * Used when combining transaction at different locations to figure out which + * one goes first. + */ +@property(nonatomic, strong) NSNumber *order; +/** + * Whether to raise local events for this transaction + */ +@property(nonatomic) BOOL applyLocally; + +/** + * Count how many times we've retried the transaction + */ +@property(nonatomic) int retryCount; + +/** + * Function to call to clean up our listener + */ +@property(nonatomic, copy) fbt_void_void unwatcher; + +/** + * Stores why a transaction was aborted + */ +@property(nonatomic, strong, readonly) NSString *abortStatus; +@property(nonatomic, strong, readonly) NSString *abortReason; + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason; +- (NSError *)abortError; + +@property(nonatomic, strong) NSNumber *currentWriteId; + +/** + * Stores the input snapshot, before the update + */ +@property(nonatomic, strong) id currentInputSnapshot; + +/** + * Stores the unresolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotRaw; + +/** + * Stores the resolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotResolved; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m new file mode 100644 index 00000000..68977efc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTransaction.h" +#import "FUtilities.h" + +@interface FTupleTransaction () + +@property(nonatomic, strong) NSString *abortStatus; +@property(nonatomic, strong) NSString *abortReason; + +@end + +@implementation FTupleTransaction + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason { + self.abortStatus = abortStatus; + self.abortReason = reason; +} + +- (NSError *)abortError { + return (self.abortStatus != nil) + ? [FUtilities errorForStatus:self.abortStatus + andReason:self.abortReason] + : nil; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h new file mode 100644 index 00000000..b94eef63 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FTypedefs.h" +#import + +@interface FTupleUserCallback : NSObject + +- (id)initWithHandle:(NSUInteger)handle; + +@property(nonatomic, copy) + fbt_void_datasnapshot_nsstring datasnapshotPrevnameCallback; +@property(nonatomic, copy) fbt_void_datasnapshot datasnapshotCallback; +@property(nonatomic, copy) fbt_void_nserror cancelCallback; +@property(nonatomic, copy) FQueryParams *queryParams; +@property(nonatomic) NSUInteger handle; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m new file mode 100644 index 00000000..ba5861fb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleUserCallback.h" + +@implementation FTupleUserCallback + +@synthesize datasnapshotCallback; +@synthesize datasnapshotPrevnameCallback; +@synthesize cancelCallback; +@synthesize queryParams; +@synthesize handle; + +- (id)initWithHandle:(NSUInteger)theHandle { + self = [super init]; + if (self) { + self.handle = theHandle; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h new file mode 100644 index 00000000..3ab74762 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h @@ -0,0 +1,21 @@ +#import +#import "FImmutableSortedDictionary.h" + +/** + * This is an array backed implementation of FImmutableSortedDictionary. It uses arrays and linear lookups to achieve + * good memory efficiency while maintaining good performance for small collections. It also uses less allocations than + * a comparable red black tree. To avoid degrading performance with increasing collection size it will automatically + * convert to a FTreeSortedDictionary after an insert call above a certain threshold. + */ +@interface FArraySortedDictionary : FImmutableSortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (id)initWithComparator:(NSComparator)comparator; + +#pragma mark - +#pragma mark Properties + +@property (nonatomic, copy, readonly) NSComparator comparator; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m new file mode 100644 index 00000000..15d2d8bd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m @@ -0,0 +1,266 @@ +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +@interface FArraySortedDictionaryEnumerator : NSEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse; +- (id)nextObject; + +@property (nonatomic) NSInteger pos; +@property (nonatomic) BOOL reverse; +@property (nonatomic, strong) NSArray *keys; + +@end + +@implementation FArraySortedDictionaryEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse +{ + self = [super init]; + if (self != nil) { + self->_pos = pos; + self->_reverse = reverse; + self->_keys = keys; + } + return self; +} + +- (id)nextObject +{ + NSInteger pos = self->_pos; + if (pos >= 0 && pos < self.keys.count) { + if (self.reverse) { + self->_pos--; + } else { + self->_pos++; + } + return self.keys[pos]; + } else { + return nil; + } +} + +@end + +@interface FArraySortedDictionary () + +- (id)initWithComparator:(NSComparator)comparator; + +@property (nonatomic, copy, readwrite) NSComparator comparator; +@property (nonatomic, strong) NSArray *keys; +@property (nonatomic, strong) NSArray *values; + +@end + +@implementation FArraySortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + NSMutableArray *keys = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [keys addObject:key]; + }]; + [keys sortUsingComparator:comparator]; + + [keys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(keys[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + NSMutableArray *values = [NSMutableArray arrayWithCapacity:keys.count]; + NSInteger pos = 0; + for (id key in keys) { + values[pos++] = dictionary[key]; + } + NSAssert(values.count == keys.count, @"We added as many keys as values"); + return [[FArraySortedDictionary alloc] initWithComparator:comparator keys:keys values:values]; +} + +- (id)initWithComparator:(NSComparator)comparator +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = [NSArray array]; + self->_values = [NSArray array]; + } + return self; +} + +- (id)initWithComparator:(NSComparator)comparator keys:(NSArray *)keys values:(NSArray *)values +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = keys; + self->_values = values; + } + return self; +} + +- (NSInteger) findInsertPositionForKey:(id)key +{ + NSInteger newPos = 0; + while (newPos < self.keys.count && self.comparator(self.keys[newPos], key) < NSOrderedSame) { + newPos++; + } + return newPos; +} + +- (NSInteger) findKey:(id)key +{ + if (key == nil) { + return NSNotFound; + } + for (NSInteger pos = 0; pos < self.keys.count; pos++) { + NSComparisonResult result = self.comparator(key, self.keys[pos]); + if (result == NSOrderedSame) { + return pos; + } else if (result == NSOrderedAscending) { + return NSNotFound; + } + } + return NSNotFound; +} + +- (FImmutableSortedDictionary *) insertKey:(id)key withValue:(id)value +{ + NSInteger pos = [self findKey:key]; + + if (pos == NSNotFound) { + /* + * If we're above the threshold we want to convert it to a tree backed implementation to not have + * degrading performance + */ + if (self.count >= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:self.count]; + for (NSInteger i = 0; i < self.keys.count; i++) { + dict[self.keys[i]] = self.values[i]; + } + dict[key] = value; + return [FTreeSortedDictionary fromDictionary:dict withComparator:self.comparator]; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + NSInteger newPos = [self findInsertPositionForKey:key]; + [newKeys insertObject:key atIndex:newPos]; + [newValues insertObject:value atIndex:newPos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + newKeys[pos] = key; + newValues[pos] = value; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (FImmutableSortedDictionary *) removeKey:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return self; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + [newKeys removeObjectAtIndex:pos]; + [newValues removeObjectAtIndex:pos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (id) get:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return nil; + } else { + return self.values[pos]; + } +} + +- (id) getPredecessorKey:(id) key { + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + [NSException raise:NSInternalInconsistencyException format:@"Can't get predecessor key for non-existent key"]; + return nil; + } else if (pos == 0) { + return nil; + } else { + return self.keys[pos - 1]; + } +} + +- (BOOL) isEmpty { + return self.keys.count == 0; +} + +- (int) count +{ + return (int)self.keys.count; +} + +- (id) minKey +{ + return [self.keys firstObject]; +} + +- (id) maxKey +{ + return [self.keys lastObject]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + BOOL stop = NO; + for (NSInteger i = self.keys.count - 1; i >= 0; i--) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } else { + BOOL stop = NO; + for (NSInteger i = 0; i < self.keys.count; i++) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } +} + +- (BOOL) contains:(id)key { + return [self findKey:key] != NSNotFound; +} + +- (NSEnumerator *) keyEnumerator { + return [self.keys objectEnumerator]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [self.keys reverseObjectEnumerator]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + // if there's no exact match, findKeyOrInsertPosition will return the index *after* the closest match, but + // since this is a reverse iterator, we want to start just *before* the closest match. + if (startPos >= self.keys.count || self.comparator(self.keys[startPos], startKey) != NSOrderedSame) { + startPos -= 1; + } + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:YES]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h new file mode 100644 index 00000000..d6687d86 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h @@ -0,0 +1,54 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import + +/** + * The size threshold where we use a tree backed sorted map instead of an array backed sorted map. + * This is a more or less arbitrary chosen value, that was chosen to be large enough to fit most of object kind + * of Firebase data, but small enough to not notice degradation in performance for inserting and lookups. + * Feel free to empirically determine this constant, but don't expect much gain in real world performance. + */ +#define SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD 25 + +@interface FImmutableSortedDictionary : NSObject + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator; ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FImmutableSortedDictionary *) removeKey:(id)aKey; +- (id) get:(id) key; +- (id) getPredecessorKey:(id) key; +- (BOOL) isEmpty; +- (int) count; +- (id) minKey; +- (id) maxKey; +- (void) enumerateKeysAndObjectsUsingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (BOOL) contains:(id)key; +- (NSEnumerator *) keyEnumerator; +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey; +- (NSEnumerator *) reverseKeyEnumerator; +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey; + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(id)anObject forKey:(id)aKey; +- (id) objectForKey:(id)key; +- (FImmutableSortedDictionary *) removeObjectForKey:(id)aKey; + +@end + diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m new file mode 100644 index 00000000..659c63b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m @@ -0,0 +1,142 @@ +#import "FImmutableSortedDictionary.h" +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +#define THROW_ABSTRACT_METHOD_EXCEPTION(sel) do { \ + @throw [NSException exceptionWithName:NSInternalInconsistencyException \ + reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(sel)] \ + userInfo:nil]; \ +} while(0) + +@implementation FImmutableSortedDictionary + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator +{ + return [[FArraySortedDictionary alloc] initWithComparator:comparator]; +} + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + if (dictionary.count <= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + return [FArraySortedDictionary fromDictionary:dictionary withComparator:comparator]; + } else { + return [FTreeSortedDictionary fromDictionary:dictionary withComparator:comparator]; + } +} + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(insertKey:withValue:)); +} + +- (FImmutableSortedDictionary *) removeKey:(id)aKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(removeKey:)); +} + +- (id) get:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(get:)); +} + +- (id) getPredecessorKey:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(getPredecessorKey:)); +} + +- (BOOL) isEmpty { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(isEmpty)); +} + +- (int) count { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector((count))); +} + +- (id) minKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(minKey)); +} + +- (id) maxKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(maxKey)); +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsUsingBlock:)); +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsReverse:usingBlock:)); +} + +- (BOOL) contains:(id)key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(contains:)); +} + +- (NSEnumerator *) keyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumerator)); +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumeratorFrom:)); +} + +- (NSEnumerator *) reverseKeyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumerator)); +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumeratorFrom:)); +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableSortedDictionary class]]) { + return NO; + } + FImmutableSortedDictionary *other = (FImmutableSortedDictionary *)object; + if (self.count != other.count) { + return NO; + } + __block BOOL isEqual = YES; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + id otherValue = [other objectForKey:key]; + isEqual = isEqual && (value == otherValue || [value isEqual:otherValue]); + *stop = !isEqual; + }]; + return isEqual; +} + +- (NSUInteger)hash { + __block NSUInteger hash = 0; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + hash = (hash * 31 + [key hash]) * 17 + [value hash]; + }]; + return hash; +} + +- (NSString *)description { + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"{ "]; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@: %@", key, value]]; + }]; + [str appendString:@" }"]; + return str; +} + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(__unsafe_unretained id)anObject forKey:(__unsafe_unretained id)aKey { + return [self insertKey:aKey withValue:anObject]; +} + +- (FImmutableSortedDictionary *) removeObjectForKey:(__unsafe_unretained id)aKey { + return [self removeKey:aKey]; +} + +- (id) objectForKey:(__unsafe_unretained id)key { + return [self get:key]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h new file mode 100644 index 00000000..ac15c2f0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h @@ -0,0 +1,22 @@ +#import + +@interface FImmutableSortedSet : NSObject + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)array comparator:(NSComparator)comparator; + +- (BOOL)containsObject:(id)object; +- (FImmutableSortedSet *)addObject:(id)object; +- (FImmutableSortedSet *)removeObject:(id)object; +- (id)firstObject; +- (id)lastObject; +- (NSUInteger)count; +- (BOOL)isEmpty; + +- (id)predecessorEntry:(id)entry; + +- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block; +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id obj, BOOL *stop))block; + +- (NSEnumerator *)objectEnumerator; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m new file mode 100644 index 00000000..1953af1a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m @@ -0,0 +1,115 @@ +#import "FImmutableSortedSet.h" +#import "FImmutableSortedDictionary.h" + +@interface FImmutableSortedSet () + +@property (nonatomic, strong) FImmutableSortedDictionary *dictionary; + +@end + +@implementation FImmutableSortedSet + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)dictionary comparator:(NSComparator)comparator +{ + FImmutableSortedDictionary *setDict = [FImmutableSortedDictionary fromDictionary:dictionary withComparator:comparator]; + return [[FImmutableSortedSet alloc] initWithDictionary:setDict]; +} + +- (id)initWithDictionary:(FImmutableSortedDictionary *)dictionary +{ + self = [super init]; + if (self != nil) { + self->_dictionary = dictionary; + } + return self; +} + +- (BOOL)contains:(id)object +{ + return [self.dictionary contains:object]; +} + +- (FImmutableSortedSet *)addObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary insertKey:object withValue:[NSNull null]]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (FImmutableSortedSet *)removeObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary removeObjectForKey:object]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (BOOL)containsObject:(id)object +{ + return [self.dictionary contains:object]; +} + +- (id)firstObject +{ + return [self.dictionary minKey]; +} + +- (id)lastObject +{ + return [self.dictionary maxKey]; +} + +- (id)predecessorEntry:(id)entry +{ + return [self.dictionary getPredecessorKey:entry]; +} + +- (NSUInteger)count +{ + return [self.dictionary count]; +} + +- (BOOL)isEmpty +{ + return [self.dictionary isEmpty]; +} + +- (void)enumerateObjectsUsingBlock:(void (^)(id, BOOL *))block +{ + [self enumerateObjectsReverse:NO usingBlock:block]; +} + +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, BOOL *))block +{ + [self.dictionary enumerateKeysAndObjectsReverse:reverse usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; +} + +- (NSEnumerator *)objectEnumerator +{ + return [self.dictionary keyEnumerator]; +} + +- (NSString *)description +{ + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"FImmutableSortedSet ( "]; + [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@", obj]]; + }]; + [str appendString:@" )"]; + return str; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h new file mode 100644 index 00000000..833f2a55 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h @@ -0,0 +1,27 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBEmptyNode : NSObject + ++ (id)emptyNode; + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m new file mode 100644 index 00000000..3ca6f062 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m @@ -0,0 +1,72 @@ +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" + +@implementation FLLRBEmptyNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + ++ (id)emptyNode +{ + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight { + return self; +} + +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator { + FLLRBValueNode* result = [[FLLRBValueNode alloc] initWithKey:aKey withValue:aValue withColor:nil withLeft:nil withRight:nil]; + return result; +} + +- (id) remove:(id) key withComparator:(NSComparator)aComparator { + return self; +} + +- (int) count { + return 0; +} + +- (BOOL) isEmpty { + return YES; +} + +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (id) min { + return self; +} + +- (id) minKey { + return nil; +} + +- (id) maxKey { + return nil; +} + +- (BOOL) isRed { + return NO; +} + +- (int) check { + return 0; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h new file mode 100644 index 00000000..09b234c6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h @@ -0,0 +1,29 @@ +#import + +#define RED @true +#define BLACK @false + +typedef NSNumber FLLRBColor; + +@protocol FLLRBNode + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) key withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h new file mode 100644 index 00000000..50438bb3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h @@ -0,0 +1,29 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBValueNode : NSObject + + +- (id)initWithKey:(id) key withValue:(id) value withColor:(FLLRBColor*) color withLeft:(id)left withRight:(id)right; +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +- (BOOL) checkMaxDepth; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m new file mode 100644 index 00000000..831b97fc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m @@ -0,0 +1,230 @@ +#import "FLLRBValueNode.h" +#import "FLLRBEmptyNode.h" + +@implementation FLLRBValueNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + +- (id)initWithKey:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight +{ + self = [super init]; + if (self) { + self.key = aKey; + self.value = aValue; + self.color = aColor != nil ? aColor : RED; + self.left = aLeft != nil ? aLeft : [FLLRBEmptyNode emptyNode]; + self.right = aRight != nil ? aRight : [FLLRBEmptyNode emptyNode]; + } + return self; +} + +- (id)copyWith:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight { + return [[FLLRBValueNode alloc] initWithKey:(aKey != nil) ? aKey : self.key + withValue:(aValue != nil) ? aValue : self.value + withColor:(aColor != nil) ? aColor : self.color + withLeft:(aLeft != nil) ? aLeft : self.left + withRight:(aRight != nil) ? aRight : self.right]; +} + +- (int) count { + return [self.left count] + 1 + [self.right count]; +} + +- (BOOL) isEmpty { + return NO; +} + +/** +* Early terminates if aciton returns YES. +* @return The first truthy value returned by action, or the last falsey value returned by action. +*/ +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return [self.left inorderTraversal:action] || + action(self.key, self.value) || + [self.right inorderTraversal:action]; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return [self.right reverseTraversal:action] || + action(self.key, self.value) || + [self.left reverseTraversal:action]; +} + +- (id) min { + if([self.left isEmpty]) { + return self; + } + else { + return [self.left min]; + } +} + +- (id) minKey { + return [[self min] key]; +} + +- (id) maxKey { + if([self.right isEmpty]) { + return self.key; + } + else { + return [self.right maxKey]; + } +} + +- (id) insertKey:(__unsafe_unretained id) aKey forValue:(__unsafe_unretained id)aValue withComparator:(NSComparator)aComparator { + NSComparisonResult cmp = aComparator(aKey, self.key); + FLLRBValueNode* n = self; + + if(cmp == NSOrderedAscending) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left insertKey:aKey forValue:aValue withComparator:aComparator] withRight:nil]; + } + else if(cmp == NSOrderedSame) { + n = [n copyWith:nil withValue:aValue withColor:nil withLeft:nil withRight:nil]; + } + else { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right insertKey:aKey forValue:aValue withComparator:aComparator]]; + } + + return [n fixUp]; +} + +- (id) removeMin { + + if([self.left isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + + FLLRBValueNode* n = self; + if(! [n.left isRed] && ! [n.left.left isRed]) { + n = [n moveRedLeft]; + } + + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[(FLLRBValueNode*)n.left removeMin] withRight:nil]; + return [n fixUp]; +} + + +- (id) fixUp { + FLLRBValueNode* n = self; + if([n.right isRed] && ! [n.left isRed]) n = [n rotateLeft]; + if([n.left isRed] && [n.left.left isRed]) n = [n rotateRight]; + if([n.left isRed] && [n.right isRed]) n = [n colorFlip]; + return n; +} + +- (FLLRBValueNode*) moveRedLeft { + FLLRBValueNode* n = [self colorFlip]; + if([n.right.left isRed]) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right rotateRight]]; + n = [n rotateLeft]; + n = [n colorFlip]; + } + return n; +} + +- (FLLRBValueNode*) moveRedRight { + FLLRBValueNode* n = [self colorFlip]; + if([n.left.left isRed]) { + n = [n rotateRight]; + n = [n colorFlip]; + } + return n; +} + +- (id) rotateLeft { + id nl = [self copyWith:nil withValue:nil withColor:RED withLeft:nil withRight:self.right.left]; + return [self.right copyWith:nil withValue:nil withColor:self.color withLeft:nl withRight:nil];; +} + +- (id) rotateRight { + id nr = [self copyWith:nil withValue:nil withColor:RED withLeft:self.left.right withRight:nil]; + return [self.left copyWith:nil withValue:nil withColor:self.color withLeft:nil withRight:nr]; +} + +- (id) colorFlip { + id nleft = [self.left copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.left.color boolValue]] withLeft:nil withRight:nil]; + id nright = [self.right copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.right.color boolValue]] withLeft:nil withRight:nil]; + + return [self copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.color boolValue]] withLeft:nleft withRight:nright]; +} + +- (id) remove:(__unsafe_unretained id) aKey withComparator:(NSComparator)comparator { + id smallest; + FLLRBValueNode* n = self; + + if(comparator(aKey, n.key) == NSOrderedAscending) { + if(![n.left isEmpty] && ![n.left isRed] && ![n.left.left isRed]) { + n = [n moveRedLeft]; + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left remove:aKey withComparator:comparator] withRight:nil]; + } + else { + if([n.left isRed]) { + n = [n rotateRight]; + } + + if(![n.right isEmpty] && ![n.right isRed] && ![n.right.left isRed]) { + n = [n moveRedRight]; + } + + if(comparator(aKey, n.key) == NSOrderedSame) { + if([n.right isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + else { + smallest = [n.right min]; + n = [n copyWith:smallest.key withValue:smallest.value withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right removeMin]]; + } + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right remove:aKey withComparator:comparator]]; + } + return [n fixUp]; +} + +- (BOOL) isRed { + return [self.color boolValue]; +} + +- (BOOL) checkMaxDepth { + int blackDepth = [self check]; + if(pow(2.0, blackDepth) <= ([self count] + 1)) { + return YES; + } + else { + return NO; + } +} + +- (int) check { + int blackDepth = 0; + + if([self isRed] && [self.left isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Red node has a red child" userInfo:nil]; + } + + if([self.right isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Right child is red" userInfo:nil]; + } + + blackDepth = [self.left check]; +// NSLog(err); + if(blackDepth != [self.right check]) { + NSString* err = [NSString stringWithFormat:@"(%@ -> %@)blackDepth: %d ; self.right check: %d", self.value, [self.color boolValue] ? @"red" : @"black", blackDepth, [self.right check]]; +// return 10; + @throw [[NSException alloc] initWithName:@"check" reason:err userInfo:nil]; + } + else { + int ret = blackDepth + ([self isRed] ? 0 : 1); +// NSLog(@"black depth is: %d; other is: %d, ret is: %d", blackDepth, ([self isRed] ? 0 : 1), ret); + return ret; + } +} + + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h new file mode 100644 index 00000000..934ca8b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h @@ -0,0 +1,30 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import +#import "FImmutableSortedDictionary.h" +#import "FLLRBNode.h" + +@interface FTreeSortedDictionary : FImmutableSortedDictionary + +@property (nonatomic, copy, readonly) NSComparator comparator; +@property (nonatomic, strong, readonly) id root; + +- (id)initWithComparator:(NSComparator)aComparator; + +// Override methods to return subtype +- (FTreeSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FTreeSortedDictionary *) removeKey:(id)aKey; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m new file mode 100644 index 00000000..e9f0683a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m @@ -0,0 +1,326 @@ +#import "FTreeSortedDictionary.h" +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FTreeSortedDictionaryEnumerator.h" + +typedef void (^fbt_void_nsnumber_int)(NSNumber* color, NSUInteger chunkSize); + +@interface FTreeSortedDictionary () + +@property (nonatomic, strong) id root; +@property (nonatomic, copy, readwrite) NSComparator comparator; + +@end + +@implementation FTreeSortedDictionary + +- (id)initWithComparator:(NSComparator)aComparator { + self = [super init]; + if (self) { + self.root = [FLLRBEmptyNode emptyNode]; + self.comparator = aComparator; + } + return self; +} + +- (id)initWithComparator:(NSComparator)aComparator withRoot:(__unsafe_unretained id)aRoot { + self = [super init]; + if (self) { + self.root = aRoot; + self.comparator = aComparator; + } + return self; +} + +/** + * Returns a copy of the map, with the specified key/value added or replaced. + */ +- (FTreeSortedDictionary *) insertKey:(__unsafe_unretained id)aKey withValue:(__unsafe_unretained id)aValue { + return [[FTreeSortedDictionary alloc] initWithComparator:self.comparator + withRoot:[[self.root insertKey:aKey forValue:aValue withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; +} + + +- (FTreeSortedDictionary *) removeKey:(__unsafe_unretained id)aKey { + // Remove is somewhat expensive even if the key doesn't exist (the tree does rebalancing and stuff). So avoid it. + if (![self contains:aKey]) { + return self; + } else { + return [[FTreeSortedDictionary alloc] + initWithComparator:self.comparator + withRoot:[[self.root remove:aKey withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; + } +} + +- (id) get:(__unsafe_unretained id) key { + if (key == nil) { + return nil; + } + NSComparisonResult cmp; + id node = self.root; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + return node.value; + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else { + node = node.right; + } + } + return nil; +} + +- (id) getPredecessorKey:(__unsafe_unretained id) key { + NSComparisonResult cmp; + id node = self.root; + id rightParent = nil; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + if(![node.left isEmpty]) { + node = node.left; + while(! [node.right isEmpty]) { + node = node.right; + } + return node.key; + } + else if (rightParent != nil) { + return rightParent.key; + } + else { + return nil; + } + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else if (cmp == NSOrderedDescending) { + rightParent = node; + node = node.right; + } + } + @throw [NSException exceptionWithName:@"NonexistentKey" reason:@"getPredecessorKey called with nonexistent key." userInfo:@{@"key": [key description] }]; +} + +- (BOOL) isEmpty { + return [self.root isEmpty]; +} + +- (int) count { + return [self.root count]; +} + +- (id) minKey { + return [self.root minKey]; +} + +- (id) maxKey { + return [self.root maxKey]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + __block BOOL stop = NO; + [self.root reverseTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } else { + __block BOOL stop = NO; + [self.root inorderTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } +} + +- (BOOL) contains:(__unsafe_unretained id)key { + return ([self objectForKey:key] != nil); +} + +- (NSEnumerator *) keyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:NO]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:YES]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:YES]; +} + + +#pragma mark - +#pragma mark Tree Builder + +// Code to efficiently build a RB Tree +typedef struct _base1_2list { + unsigned int bits; + unsigned short count; + unsigned short current; +} Base1_2List; + +Base1_2List *base1_2List_new(unsigned int length); +void base1_2List_free(Base1_2List* list); +unsigned int log_base2(unsigned int num); +BOOL base1_2List_next(Base1_2List* list); + +unsigned int log_base2(unsigned int num) { + return (unsigned int)(log(num) / log(2)); +} + +/** + * Works like an iterator, so it moves to the next bit. Do not call more than list->count times. + * @return whether or not the next bit is a 1 in base {1,2}. + */ +BOOL base1_2List_next(Base1_2List* list) { + BOOL result = !(list->bits & (0x1 << list->current)); + list->current--; + return result; +} + +static inline unsigned bit_mask(int x) { + return (x >= sizeof(unsigned) * CHAR_BIT) ? (unsigned) -1 : (1U << x) - 1; +} + +/** + * We represent the base{1,2} number as the combination of a binary number and a number of bits that we care about + * We iterate backwards, from most significant bit to least, to build up the llrb nodes. 0 base 2 => 1 base {1,2}, 1 base 2 => 2 base {1,2} + */ +Base1_2List *base1_2List_new(unsigned int length) { + size_t sz = sizeof(Base1_2List); + Base1_2List* list = calloc(1, sz); + // Calculate the number of bits that we care about + list->count = (unsigned short)log_base2(length + 1); + unsigned int mask = bit_mask(list->count); + list->bits = (length + 1) & mask; + list->current = list->count - 1; + return list; +} + + +void base1_2List_free(Base1_2List* list) { + free(list); +} + ++ (id) buildBalancedTree:(NSArray *)keys dictionary:(NSDictionary *)dictionary subArrayStartIndex:(NSUInteger)startIndex length:(NSUInteger)length { + length = MIN(keys.count - startIndex, length); // Bound length by the actual length of the array + if (length == 0) { + return nil; + } else if (length == 1) { + id key = keys[startIndex]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:nil withRight:nil]; + } else { + NSUInteger middle = length / 2; + id left = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:startIndex length:middle]; + id right = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:(startIndex+middle+1) length:middle]; + id key = keys[startIndex + middle]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:left withRight:right]; + } +} + ++ (id) rootFrom12List:(Base1_2List *)base1_2List keyList:(NSArray *)keyList dictionary:(NSDictionary *)dictionary { + __block id root = nil; + __block id node = nil; + __block NSUInteger index = keyList.count; + + fbt_void_nsnumber_int buildPennant = ^(NSNumber* color, NSUInteger chunkSize) { + NSUInteger startIndex = index - chunkSize + 1; + index -= chunkSize; + id key = keyList[index]; + id childTree = [self buildBalancedTree:keyList dictionary:dictionary subArrayStartIndex:startIndex length:(chunkSize - 1)]; + id pennant = [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:color withLeft:nil withRight:childTree]; + //attachPennant(pennant); + if (node) { + node.left = pennant; + node = pennant; + } else { + root = pennant; + node = pennant; + } + }; + + for (int i = 0; i < base1_2List->count; ++i) { + BOOL isOne = base1_2List_next(base1_2List); + NSUInteger chunkSize = (NSUInteger)pow(2.0, base1_2List->count - (i + 1)); + if (isOne) { + buildPennant(BLACK, chunkSize); + } else { + buildPennant(BLACK, chunkSize); + buildPennant(RED, chunkSize); + } + } + return root; +} + +/** + * Uses the algorithm linked here: + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458 + */ + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + // Steps: + // 0. Sort the array + // 1. Calculate the 1-2 number + // 2. Build From 1-2 number + // 0. for each digit in 1-2 number + // 0. calculate chunk size + // 1. build 1 or 2 pennants of that size + // 2. attach pennants and update node pointer + // 1. return root + NSMutableArray *sortedKeyList = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [sortedKeyList addObject:key]; + }]; + [sortedKeyList sortUsingComparator:comparator]; + + [sortedKeyList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(sortedKeyList[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + Base1_2List* list = base1_2List_new((unsigned int)sortedKeyList.count); + id root = [self rootFrom12List:list keyList:sortedKeyList dictionary:dictionary]; + base1_2List_free(list); + + if (root != nil) { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator withRoot:root]; + } else { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator]; + } +} + +@end + diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h new file mode 100644 index 00000000..d79fe8e6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h @@ -0,0 +1,9 @@ +#import +#import "FTreeSortedDictionary.h" + +@interface FTreeSortedDictionaryEnumerator : NSEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict startKey:(id)startKey isReverse:(BOOL)reverse; +- (id)nextObject; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m new file mode 100644 index 00000000..2aca86e0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m @@ -0,0 +1,83 @@ +#import "FTreeSortedDictionaryEnumerator.h" + +@interface FTreeSortedDictionaryEnumerator() +@property (nonatomic, strong) FTreeSortedDictionary* immutableSortedDictionary; +@property (nonatomic, strong) NSMutableArray* stack; +@property (nonatomic) BOOL isReverse; + +@end + +@implementation FTreeSortedDictionaryEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict + startKey:(id)startKey isReverse:(BOOL)reverse { + self = [super init]; + if (self) { + self.immutableSortedDictionary = aDict; + self.stack = [[NSMutableArray alloc] init]; + self.isReverse = reverse; + + NSComparator comparator = aDict.comparator; + id node = self.immutableSortedDictionary.root; + + NSInteger cmp; + while(![node isEmpty]) { + cmp = startKey ? comparator(node.key, startKey) : 1; + // flip the comparison if we're going in reverse + if (self.isReverse) cmp *= -1; + + if (cmp < 0) { + // This node is less than our start key. Ignore it. + if (self.isReverse) { + node = node.left; + } else { + node = node.right; + } + } else if (cmp == 0) { + // This node is exactly equal to our start key. Push it on the stack, but stop iterating: + [self.stack addObject:node]; + break; + } else { + // This node is greater than our start key, add it to the stack and move on to the next one. + [self.stack addObject:node]; + if (self.isReverse) { + node = node.right; + } else { + node = node.left; + } + } + } + } + return self; +} + +- (id)nextObject { + if([self.stack count] == 0) { + return nil; + } + + id node = nil; + @synchronized(self.stack) { + node = [self.stack lastObject]; + [self.stack removeLastObject]; + } + id result = node.key; + + if (self.isReverse) { + node = node.left; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.right; + } + } else { + node = node.right; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.left; + } + } + + return result; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h new file mode 100644 index 00000000..76f87dea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h @@ -0,0 +1,107 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import + +typedef enum { + SR_CONNECTING = 0, + SR_OPEN = 1, + SR_CLOSING = 2, + SR_CLOSED = 3, + +} FSRReadyState; + +@class FSRWebSocket; + +extern NSString *const FSRWebSocketErrorDomain; + +@protocol FSRWebSocketDelegate; + +@interface FSRWebSocket : NSObject + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, readonly) FSRReadyState readyState; +@property (nonatomic, readonly, retain) NSURL *url; + +// This returns the negotiated protocol. +// It will be niluntil after the handshake completes. +@property (nonatomic, readonly, copy) NSString *protocol; + +// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue googleAppID:(NSString*)googleAppID andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue googleAppID:(NSString*)googleAppID andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request; + +// Some helper constructors +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +- (id)initWithURL:(NSURL *)url; + +// Delegate queue will be dispatch_main_queue by default. +// You cannot set both OperationQueue and dispatch_queue. +- (void)setDelegateOperationQueue:(NSOperationQueue*) queue; +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; + +// By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes. +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; + +// SRWebSockets are intended one-time-use only. Open should be called once and only once +- (void)open; + +- (void)close; +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; + +// Send a UTF8 String or Data +- (void)send:(id)data; + +@end + +@protocol FSRWebSocketDelegate + +// message will either be an NSString if the server is using text +// or NSData if the server is using binary +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; + +@optional + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; + +@end + + +@interface NSURLRequest (FCertificateAdditions) + +@property (nonatomic, retain, readonly) NSArray *FSR_SSLPinnedCertificates; + +@end + + +@interface NSMutableURLRequest (FCertificateAdditions) + +@property (nonatomic, retain) NSArray *FSR_SSLPinnedCertificates; + +@end + +@interface NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m new file mode 100644 index 00000000..1bdff9a3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m @@ -0,0 +1,1867 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FSRWebSocket.h" + +#if __has_include() +#define HAS_ICU +#endif + +#import + +#ifdef HAS_ICU +#import +#endif + +#if __has_include() +#import +#else +#import +#endif + +#import +#import +#import "fbase64.h" +#import "NSData+SRB64Additions.h" + +#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE +#define sr_dispatch_retain(x) +#define sr_dispatch_release(x) +#define maybe_bridge(x) ((__bridge void *) x) +#else +#define sr_dispatch_retain(x) dispatch_retain(x) +#define sr_dispatch_release(x) dispatch_release(x) +#define maybe_bridge(x) (x) +#endif + +typedef enum { + SROpCodeTextFrame = 0x1, + SROpCodeBinaryFrame = 0x2, + //3-7Reserved + SROpCodeConnectionClose = 0x8, + SROpCodePing = 0x9, + SROpCodePong = 0xA, + //B-F reserved +} FSROpCode; + +typedef enum { + SRStatusCodeNormal = 1000, + SRStatusCodeGoingAway = 1001, + SRStatusCodeProtocolError = 1002, + SRStatusCodeUnhandledType = 1003, + // 1004 reserved + SRStatusNoStatusReceived = 1005, + // 1004-1006 reserved + SRStatusCodeInvalidUTF8 = 1007, + SRStatusCodePolicyViolated = 1008, + SRStatusCodeMessageTooBig = 1009, +} FSRStatusCode; + +typedef struct { + BOOL fin; +// BOOL rsv1; +// BOOL rsv2; +// BOOL rsv3; + uint8_t opcode; + BOOL masked; + uint64_t payload_length; +} frame_header; + +static NSString *const SRWebSocketAppendToSecKeyString = @"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + +static inline int32_t validate_dispatch_data_partial_string(NSData *data); +static inline void SRFastLog(NSString *format, ...); + +@interface NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSURL (FSRWebSocket) + +// The origin isn't really applicable for a native application +// So instead, just map ws -> http and wss -> https +- (NSString *)SR_origin; + +@end + +@interface _FSRRunLoopThread : NSThread + +@property (nonatomic, readonly) NSRunLoop *runLoop; + +@end + +static NSString *newSHA1String(const char *bytes, size_t length) { + uint8_t md[CC_SHA1_DIGEST_LENGTH]; + + CC_SHA1(bytes, (int)length, md); + + size_t buffer_size = ((sizeof(md) * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(md, CC_SHA1_DIGEST_LENGTH, buffer, buffer_size); + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSASCIIStringEncoding freeWhenDone:YES]; + } +} + +@implementation NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.bytes, self.length); +} + +@end + + +@implementation NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.UTF8String, self.length); +} + +@end + +NSString *const FSRWebSocketErrorDomain = @"FSRWebSocketErrorDomain"; + +// Returns number of bytes consumed. returning 0 means you didn't match. +// Sends bytes to callback handler; +typedef size_t (^stream_scanner)(NSData *collected_data); + +typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data); + +@interface FSRIOConsumer : NSObject { + stream_scanner _scanner; + data_callback _handler; + size_t _bytesNeeded; + BOOL _readToCurrentFrame; + BOOL _unmaskBytes; +} +@property (nonatomic, copy, readonly) stream_scanner consumer; +@property (nonatomic, copy, readonly) data_callback handler; +@property (nonatomic, assign) size_t bytesNeeded; +@property (nonatomic, assign, readonly) BOOL readToCurrentFrame; +@property (nonatomic, assign, readonly) BOOL unmaskBytes; + +@end + +// This class is not thread-safe, and is expected to always be run on the same queue. +@interface FSRIOConsumerPool : NSObject + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)returnConsumer:(FSRIOConsumer *)consumer; + +@end + +@interface FSRWebSocket () + +- (void)_writeData:(NSData *)data; +- (void)_closeWithProtocolError:(NSString *)message; +- (void)_failWithError:(NSError *)error; + +- (void)_disconnect; + +- (void)_readFrameNew; +- (void)_readFrameContinue; + +- (void)_pumpScanner; + +- (void)_pumpWriting; + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +- (void)_SR_commonInit; + +- (void)_initializeStreams; +- (void)_connect; + +@property (nonatomic) FSRReadyState readyState; + +@property (nonatomic) NSOperationQueue *delegateOperationQueue; +@property (nonatomic) dispatch_queue_t delegateDispatchQueue; + +@end + + +@implementation FSRWebSocket { + NSInteger _webSocketVersion; + + NSOperationQueue *_delegateOperationQueue; + dispatch_queue_t _delegateDispatchQueue; + dispatch_queue_t _workQueue; + NSMutableArray *_consumers; + + NSInputStream *_inputStream; + NSOutputStream *_outputStream; + + NSMutableData *_readBuffer; + NSInteger _readBufferOffset; + + NSMutableData *_outputBuffer; + NSInteger _outputBufferOffset; + + uint8_t _currentFrameOpcode; + size_t _currentFrameCount; + size_t _readOpCount; + uint32_t _currentStringScanPosition; + NSMutableData *_currentFrameData; + + NSString *_closeReason; + + NSString *_secKey; + + BOOL _pinnedCertFound; + + uint8_t _currentReadMaskKey[4]; + size_t _currentReadMaskOffset; + + BOOL _consumerStopped; + + BOOL _closeWhenFinishedWriting; + BOOL _failed; + + BOOL _secure; + NSURLRequest *_urlRequest; + NSString *_userAgent; + NSString *_googleAppID; + + CFHTTPMessageRef _receivedHTTPHeaders; + + BOOL _sentClose; + BOOL _didFail; + BOOL _cleanupScheduled; + int _closeCode; + + BOOL _isPumping; + + NSMutableSet *_scheduledRunloops; + + // We use this to retain ourselves. + __strong FSRWebSocket *_selfRetain; + + NSArray *_requestedProtocols; + FSRIOConsumerPool *_consumerPool; +} + +@synthesize delegate = _delegate; +@synthesize url = _url; +@synthesize readyState = _readyState; +@synthesize protocol = _protocol; + +static __strong NSData *CRLFCRLF; + ++ (void)initialize; +{ + CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue + googleAppID:(NSString *)googleAppID andUserAgent:(NSString *)userAgent; +{ + self = [super init]; + if (self) { + assert(request.URL); + _url = request.URL; + NSString *scheme = [_url scheme]; + + _requestedProtocols = [protocols copy]; + _googleAppID = googleAppID; + _userAgent = userAgent; + + assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]); + _urlRequest = request; + + if ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]) { + _secure = YES; + } + + if (!queue) { + _delegateDispatchQueue = dispatch_get_main_queue(); + } else { + _delegateDispatchQueue = queue; + } + + [self _SR_commonInit]; + } + + return self; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +{ + return [self initWithURLRequest:request protocols:nil queue:nil googleAppID:nil andUserAgent:nil]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue + googleAppID:(NSString *)googleAppID andUserAgent:(NSString *)userAgent; +{ + return [self initWithURLRequest:request protocols:nil queue:queue googleAppID:googleAppID + andUserAgent:userAgent]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request; +{ + return [self initWithURLRequest:request protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url; +{ + return [self initWithURL:url protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +{ + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + return [self initWithURLRequest:request protocols:protocols]; +} + +- (void)_SR_commonInit; +{ + _readyState = SR_CONNECTING; + + _consumerStopped = YES; + + _webSocketVersion = 13; + + _workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + + // Going to set a specific on the queue so we can validate we're on the work queue + dispatch_queue_set_specific(_workQueue, (__bridge void *)self, maybe_bridge(_workQueue), NULL); + + sr_dispatch_retain(_delegateDispatchQueue); + + _readBuffer = [[NSMutableData alloc] init]; + _outputBuffer = [[NSMutableData alloc] init]; + + _currentFrameData = [[NSMutableData alloc] init]; + + _consumers = [[NSMutableArray alloc] init]; + + _consumerPool = [[FSRIOConsumerPool alloc] init]; + + _scheduledRunloops = [[NSMutableSet alloc] init]; + + [self _initializeStreams]; + + // default handlers +} + +- (void)assertOnWorkQueue; +{ + assert(dispatch_get_specific((__bridge void *)self) == maybe_bridge(_workQueue)); +} + +- (void)dealloc +{ + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + [_inputStream close]; + [_outputStream close]; + + sr_dispatch_release(_workQueue); + _workQueue = NULL; + + if (_receivedHTTPHeaders) { + CFRelease(_receivedHTTPHeaders); + _receivedHTTPHeaders = NULL; + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + _delegateDispatchQueue = NULL; + } +} + +#ifndef NDEBUG + +- (void)setReadyState:(FSRReadyState)aReadyState; +{ + [self willChangeValueForKey:@"readyState"]; + assert(aReadyState > _readyState); + _readyState = aReadyState; + [self didChangeValueForKey:@"readyState"]; +} + +#endif + +- (void)open; +{ + assert(_url); + NSAssert(_readyState == SR_CONNECTING, @"Cannot call -(void)open on SRWebSocket more than once"); + + _selfRetain = self; + + [self _connect]; +} + +// Calls block on delegate queue +- (void)_performDelegateBlock:(dispatch_block_t)block; +{ + if (_delegateOperationQueue) { + [_delegateOperationQueue addOperationWithBlock:block]; + } else { + assert(_delegateDispatchQueue); + dispatch_async(_delegateDispatchQueue, block); + } +} + +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; +{ + if (queue) { + sr_dispatch_retain(queue); + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + } + + _delegateDispatchQueue = queue; +} + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +{ + NSString *acceptHeader = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(httpMessage, CFSTR("Sec-WebSocket-Accept"))); + + if (acceptHeader == nil) { + return NO; + } + + NSString *concattedString = [_secKey stringByAppendingString:SRWebSocketAppendToSecKeyString]; + NSString *expectedAccept = [concattedString stringBySHA1ThenBase64Encoding]; + + return [acceptHeader isEqualToString:expectedAccept]; +} + +- (void)_HTTPHeadersDidFinish; +{ + NSInteger responseCode = CFHTTPMessageGetResponseStatusCode(_receivedHTTPHeaders); + + if (responseCode >= 400) { + SRFastLog(@"Request failed with response code %d", responseCode); + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2132 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"received bad response code from server %u", (int)responseCode] forKey:NSLocalizedDescriptionKey]]]; + return; + + } + + if(![self _checkHandshake:_receivedHTTPHeaders]) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Invalid Sec-WebSocket-Accept response"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + NSString *negotiatedProtocol = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(_receivedHTTPHeaders, CFSTR("Sec-WebSocket-Protocol"))); + if (negotiatedProtocol) { + // Make sure we requested the protocol + if ([_requestedProtocols indexOfObject:negotiatedProtocol] == NSNotFound) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Server specified Sec-WebSocket-Protocol that wasn't requested"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _protocol = negotiatedProtocol; + } + + self.readyState = SR_OPEN; + + if (!_didFail) { + [self _readFrameNew]; + } + + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocketDidOpen:)]) { + [self.delegate webSocketDidOpen:self]; + }; + }]; +} + + +- (void)_readHTTPHeader; +{ + if (_receivedHTTPHeaders == NULL) { + _receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO); + } + + [self _readUntilHeaderCompleteWithCallback:^(FSRWebSocket *self, NSData *data) { + CFHTTPMessageAppendBytes(self->_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length); + + if (CFHTTPMessageIsHeaderComplete(self->_receivedHTTPHeaders)) { + SRFastLog(@"Finished reading headers %@", CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(self->_receivedHTTPHeaders))); + [self _HTTPHeadersDidFinish]; + } else { + [self _readHTTPHeader]; + } + }]; +} + +- (void)didConnect +{ + SRFastLog(@"Connected"); + CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1); + + // Set host first so it defaults + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef) + (_url.port != nil ? [NSString stringWithFormat:@"%@:%@", + _url.host, _url.port] : _url.host)); + + NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16]; + int result = SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes); + assert(result == 0); + _secKey = [FSRUtilities base64EncodedStringFromData:keyBytes]; + assert([_secKey length] == 24); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Upgrade"), CFSTR("websocket")); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Upgrade")); + if (_userAgent) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("User-Agent"), (__bridge CFStringRef)_userAgent); + } + + if (_googleAppID) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("X-Firebase-GMPID"), (__bridge CFStringRef)_googleAppID); + } + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%u", (int)_webSocketVersion]); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.SR_origin); + + if (_requestedProtocols) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]); + } + + [_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj); + }]; + + NSData *message = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(request)); + + CFRelease(request); + + [self _writeData:message]; + [self _readHTTPHeader]; +} + +//- (void)_connectToHost:(NSString *)host port:(NSInteger)port; +- (void)_initializeStreams; +{ + NSInteger port = _url.port.integerValue; + if (port == 0) { + if (!_secure) { + port = 80; + } else { + port = 443; + } + } + NSString *host = _url.host; + + CFReadStreamRef readStream = NULL; + CFWriteStreamRef writeStream = NULL; + + CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, (int)port, &readStream, &writeStream); + + // XXX + CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + + _outputStream = CFBridgingRelease(writeStream); + _inputStream = CFBridgingRelease(readStream); + + + if (_secure) { + NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init]; + + [_outputStream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel]; + + // If we're using pinned certs, don't validate the certificate chain + if ([_urlRequest FSR_SSLPinnedCertificates].count) { + [SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain]; + } + + [_outputStream setProperty:SSLOptions + forKey:(__bridge id)kCFStreamPropertySSLSettings]; + } + + _inputStream.delegate = self; + _outputStream.delegate = self; + + [_outputStream open]; + [_inputStream open]; +} + +- (void)_connect; +{ + if (!_scheduledRunloops.count) { + [self scheduleInRunLoop:[NSRunLoop FSR_networkRunLoop] forMode:NSDefaultRunLoopMode]; + } + + + [_outputStream open]; + [_inputStream open]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream scheduleInRunLoop:aRunLoop forMode:mode]; + [_inputStream scheduleInRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops addObject:@[aRunLoop, mode]]; +} + +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream removeFromRunLoop:aRunLoop forMode:mode]; + [_inputStream removeFromRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops removeObject:@[aRunLoop, mode]]; +} + +- (void)close; +{ + [self closeWithCode:-1 reason:nil]; +} + +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; +{ + assert(code); + dispatch_async(_workQueue, ^{ + if (self.readyState == SR_CLOSING || self.readyState == SR_CLOSED) { + return; + } + + BOOL wasConnecting = self.readyState == SR_CONNECTING; + + self.readyState = SR_CLOSING; + + SRFastLog(@"Closing with code %d reason %@", code, reason); + + if (wasConnecting) { + [self _disconnect]; + return; + } + + size_t maxMsgSize = [reason maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSMutableData *mutablePayload = [[NSMutableData alloc] initWithLength:sizeof(uint16_t) + maxMsgSize]; + NSData *payload = mutablePayload; + + ((uint16_t *)mutablePayload.mutableBytes)[0] = EndianU16_BtoN(code); + + if (reason) { + NSRange remainingRange = {0}; + + NSUInteger usedLength = 0; + + BOOL success = [reason getBytes:(char *)mutablePayload.mutableBytes + sizeof(uint16_t) maxLength:payload.length - sizeof(uint16_t) usedLength:&usedLength encoding:NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0, reason.length) remainingRange:&remainingRange]; + + assert(success); + assert(remainingRange.length == 0); + + if (usedLength != maxMsgSize) { + payload = [payload subdataWithRange:NSMakeRange(0, usedLength + sizeof(uint16_t))]; + } + } + + + [self _sendFrameWithOpcode:SROpCodeConnectionClose data:payload]; + }); +} + +- (void)_closeWithProtocolError:(NSString *)message; +{ + // Need to shunt this on the _callbackQueue first to see if they received any messages + [self _performDelegateBlock:^{ + [self closeWithCode:SRStatusCodeProtocolError reason:message]; + dispatch_async(self->_workQueue, ^{ + [self _disconnect]; + }); + }]; +} + +- (void)_failWithError:(NSError *)error; +{ + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self->_failed = YES; + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) { + [self.delegate webSocket:self didFailWithError:error]; + } + }]; + + self.readyState = SR_CLOSED; + + SRFastLog(@"Failing with error %@", error.localizedDescription); + + [self _disconnect]; + [self _scheduleCleanup]; + } + }); +} + +- (void)_writeData:(NSData *)data; +{ + [self assertOnWorkQueue]; + + if (_closeWhenFinishedWriting) { + return; + } + [_outputBuffer appendData:data]; + [self _pumpWriting]; +} +- (void)send:(id)data; +{ + SRFastLog(@"Sending data %@", data); + NSAssert(self.readyState != SR_CONNECTING, @"Invalid State: Cannot call send: until connection is open"); + // TODO: maybe not copy this for performance + data = [data copy]; + dispatch_async(_workQueue, ^{ + if ([data isKindOfClass:[NSString class]]) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:[(NSString *)data dataUsingEncoding:NSUTF8StringEncoding]]; + } else if ([data isKindOfClass:[NSData class]]) { + [self _sendFrameWithOpcode:SROpCodeBinaryFrame data:data]; + } else if (data == nil) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:data]; + } else { + assert(NO); + } + }); +} + +- (void)handlePing:(NSData *)pingData; +{ + // Need to pingpong this off _callbackQueue first to make sure messages happen in order + [self _performDelegateBlock:^{ + dispatch_async(self->_workQueue, ^{ + [self _sendFrameWithOpcode:SROpCodePong data:pingData]; + }); + }]; +} + +- (void)handlePong; +{ + // NOOP +} + +- (void)_handleMessage:(id)message +{ + SRFastLog(@"Received message"); + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)]) { + [self.delegate webSocket:self didReceiveMessage:message]; + } + }]; +} + + +static inline BOOL closeCodeIsValid(int closeCode) { + if (closeCode < 1000) { + return NO; + } + + if (closeCode >= 1000 && closeCode <= 1011) { + if (closeCode == 1004 || + closeCode == 1005 || + closeCode == 1006) { + return NO; + } + return YES; + } + + if (closeCode >= 3000 && closeCode <= 3999) { + return YES; + } + + if (closeCode >= 4000 && closeCode <= 4999) { + return YES; + } + + return NO; +} + +// Note from RFC: +// +// If there is a body, the first two +// bytes of the body MUST be a 2-byte unsigned integer (in network byte +// order) representing a status code with value /code/ defined in +// Section 7.4. Following the 2-byte integer the body MAY contain UTF-8 +// encoded data with value /reason/, the interpretation of which is not +// defined by this specification. + +- (void)handleCloseWithData:(NSData *)data; +{ + size_t dataSize = data.length; + __block uint16_t closeCode = 0; + + SRFastLog(@"Received close frame"); + + if (dataSize == 1) { + // TODO handle error + [self _closeWithProtocolError:@"Payload for close must be larger than 2 bytes"]; + return; + } else if (dataSize >= 2) { + [data getBytes:&closeCode length:sizeof(closeCode)]; + _closeCode = EndianU16_BtoN(closeCode); + if (!closeCodeIsValid(_closeCode)) { + [self _closeWithProtocolError:[NSString stringWithFormat:@"Cannot have close code of %d", _closeCode]]; + return; + } + if (dataSize > 2) { + _closeReason = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(2, dataSize - 2)] encoding:NSUTF8StringEncoding]; + if (!_closeReason) { + [self _closeWithProtocolError:@"Close reason MUST be valid UTF-8"]; + return; + } + } + } else { + _closeCode = SRStatusNoStatusReceived; + } + + [self assertOnWorkQueue]; + + if (self.readyState == SR_OPEN) { + [self closeWithCode:1000 reason:nil]; + } + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); +} + +- (void)_disconnect; +{ + [self assertOnWorkQueue]; + SRFastLog(@"Trying to disconnect"); + _closeWhenFinishedWriting = YES; + [self _pumpWriting]; +} + +- (void)_handleFrameWithData:(NSData *)frameData opCode:(NSInteger)opcode; +{ + // Check that the current data is valid UTF8 + + BOOL isControlFrame = (opcode == SROpCodePing || opcode == SROpCodePong || opcode == SROpCodeConnectionClose); + if (!isControlFrame) { + [self _readFrameNew]; + } else { + dispatch_async(_workQueue, ^{ + [self _readFrameContinue]; + }); + } + + switch (opcode) { + case SROpCodeTextFrame: { + NSString *str = [[NSString alloc] initWithData:frameData encoding:NSUTF8StringEncoding]; + if (str == nil && frameData) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + + return; + } + [self _handleMessage:str]; + break; + } + case SROpCodeBinaryFrame: + [self _handleMessage:[frameData copy]]; + break; + case SROpCodeConnectionClose: + [self handleCloseWithData:frameData]; + break; + case SROpCodePing: + [self handlePing:frameData]; + break; + case SROpCodePong: + [self handlePong]; + break; + default: + [self _closeWithProtocolError:[NSString stringWithFormat:@"Unknown opcode %u", (int)opcode]]; + // TODO: Handle invalid opcode + break; + } +} + +- (void)_handleFrameHeader:(frame_header)frame_header curData:(NSData *)curData; +{ + assert(frame_header.opcode != 0); + + if (self.readyState != SR_OPEN) { + return; + } + + + BOOL isControlFrame = (frame_header.opcode == SROpCodePing || frame_header.opcode == SROpCodePong || frame_header.opcode == SROpCodeConnectionClose); + + if (isControlFrame && !frame_header.fin) { + [self _closeWithProtocolError:@"Fragmented control frames not allowed"]; + return; + } + + if (isControlFrame && frame_header.payload_length >= 126) { + [self _closeWithProtocolError:@"Control frames cannot have payloads larger than 126 bytes"]; + return; + } + + if (!isControlFrame) { + _currentFrameOpcode = frame_header.opcode; + _currentFrameCount += 1; + } + + if (frame_header.payload_length == 0) { + if (isControlFrame) { + [self _handleFrameWithData:curData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + } + } else { + [self _addConsumerWithDataLength:(size_t)frame_header.payload_length callback:^(FSRWebSocket *self, NSData *newData) { + if (isControlFrame) { + [self _handleFrameWithData:newData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:self->_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + + } + } readToCurrentFrame:!isControlFrame unmaskBytes:frame_header.masked]; + } +} + +/* From RFC: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16/64) | + |N|V|V|V| |S| | (if payload len==126/127) | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Extended payload length continued, if payload len == 127 | + + - - - - - - - - - - - - - - - +-------------------------------+ + | |Masking-key, if MASK set to 1 | + +-------------------------------+-------------------------------+ + | Masking-key (continued) | Payload Data | + +-------------------------------- - - - - - - - - - - - - - - - + + : Payload Data continued ... : + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + | Payload Data continued ... | + +---------------------------------------------------------------+ + */ + +static const uint8_t SRFinMask = 0x80; +static const uint8_t SROpCodeMask = 0x0F; +static const uint8_t SRRsvMask = 0x70; +static const uint8_t SRMaskMask = 0x80; +static const uint8_t SRPayloadLenMask = 0x7F; + + +- (void)_readFrameContinue; +{ + assert((_currentFrameCount == 0 && _currentFrameOpcode == 0) || (_currentFrameCount > 0 && _currentFrameOpcode > 0)); + + [self _addConsumerWithDataLength:2 callback:^(FSRWebSocket *self, NSData *data) { + __block frame_header header = {0}; + + const uint8_t *headerBuffer = data.bytes; + assert(data.length >= 2); + + if (headerBuffer[0] & SRRsvMask) { + [self _closeWithProtocolError:@"Server used RSV bits"]; + return; + } + + uint8_t receivedOpcode = (SROpCodeMask & headerBuffer[0]); + + BOOL isControlFrame = (receivedOpcode == SROpCodePing || receivedOpcode == SROpCodePong || receivedOpcode == SROpCodeConnectionClose); + + if (!isControlFrame && receivedOpcode != 0 && self->_currentFrameCount > 0) { + [self _closeWithProtocolError:@"all data frames after the initial data frame must have opcode 0"]; + return; + } + + if (receivedOpcode == 0 && self->_currentFrameCount == 0) { + [self _closeWithProtocolError:@"cannot continue a message"]; + return; + } + + header.opcode = receivedOpcode == 0 ? self->_currentFrameOpcode : receivedOpcode; + + header.fin = !!(SRFinMask & headerBuffer[0]); + + + header.masked = !!(SRMaskMask & headerBuffer[1]); + header.payload_length = SRPayloadLenMask & headerBuffer[1]; + + headerBuffer = NULL; + + if (header.masked) { + [self _closeWithProtocolError:@"Client must receive unmasked data"]; + } + + size_t extra_bytes_needed = header.masked ? sizeof(self->_currentReadMaskKey) : 0; + + if (header.payload_length == 126) { + extra_bytes_needed += sizeof(uint16_t); + } else if (header.payload_length == 127) { + extra_bytes_needed += sizeof(uint64_t); + } + + if (extra_bytes_needed == 0) { + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } else { + [self _addConsumerWithDataLength:extra_bytes_needed callback:^(FSRWebSocket *self, NSData *data) { + size_t mapped_size = data.length; + const void *mapped_buffer = data.bytes; + size_t offset = 0; + + if (header.payload_length == 126) { + assert(mapped_size >= sizeof(uint16_t)); + uint16_t newLen = EndianU16_BtoN(*(uint16_t *)(mapped_buffer)); + header.payload_length = newLen; + offset += sizeof(uint16_t); + } else if (header.payload_length == 127) { + assert(mapped_size >= sizeof(uint64_t)); + header.payload_length = EndianU64_BtoN(*(uint64_t *)(mapped_buffer)); + offset += sizeof(uint64_t); + } else { + assert(header.payload_length < 126 && header.payload_length >= 0); + } + + + if (header.masked) { + assert(mapped_size >= sizeof(self->_currentReadMaskOffset) + offset); + memcpy(self->_currentReadMaskKey, ((uint8_t *)mapped_buffer) + offset, sizeof(self->_currentReadMaskKey)); + } + + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } readToCurrentFrame:NO unmaskBytes:NO]; + } + } readToCurrentFrame:NO unmaskBytes:NO]; +} + +- (void)_readFrameNew; +{ + dispatch_async(_workQueue, ^{ + [self->_currentFrameData setLength:0]; + + self->_currentFrameOpcode = 0; + self->_currentFrameCount = 0; + self->_readOpCount = 0; + self->_currentStringScanPosition = 0; + + [self _readFrameContinue]; + }); +} + +- (void)_pumpWriting; +{ + [self assertOnWorkQueue]; + + NSUInteger dataLength = _outputBuffer.length; + if (dataLength - _outputBufferOffset > 0 && _outputStream.hasSpaceAvailable) { + NSUInteger bytesWritten = [_outputStream write:_outputBuffer.bytes + _outputBufferOffset maxLength:dataLength - _outputBufferOffset]; + if (bytesWritten == -1) { + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2145 userInfo:[NSDictionary dictionaryWithObject:@"Error writing to stream" forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _outputBufferOffset += bytesWritten; + + if (_outputBufferOffset > 4096 && _outputBufferOffset > (_outputBuffer.length >> 1)) { + _outputBuffer = [[NSMutableData alloc] initWithBytes:(char *)_outputBuffer.bytes + _outputBufferOffset length:_outputBuffer.length - _outputBufferOffset]; + _outputBufferOffset = 0; + } + } + + if (_closeWhenFinishedWriting && + _outputBuffer.length - _outputBufferOffset == 0 && + (_inputStream.streamStatus != NSStreamStatusNotOpen && + _inputStream.streamStatus != NSStreamStatusClosed) && + !_sentClose) { + _sentClose = YES; + + @synchronized (self) { + [_outputStream close]; + [_inputStream close]; + + // TODO: Why are we missing the SocketRocket code to call unscheduleFromRunLoop??? + } + + if (!_failed) { + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:self->_closeCode reason:self->_closeReason wasClean:YES]; + } + }]; + } + [self _scheduleCleanup]; + } +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +{ + [self assertOnWorkQueue]; + [self _addConsumerWithScanner:consumer callback:callback dataLength:0]; +} + +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + [self assertOnWorkQueue]; + assert(dataLength); + + [_consumers addObject:[_consumerPool consumerWithScanner:nil handler:callback bytesNeeded:dataLength readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]]; + [self _pumpScanner]; +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +{ + [self assertOnWorkQueue]; + [_consumers addObject:[_consumerPool consumerWithScanner:consumer handler:callback bytesNeeded:dataLength readToCurrentFrame:NO unmaskBytes:NO]]; + [self _pumpScanner]; +} + + +- (void)_scheduleCleanup +{ + @synchronized(self) { + if (_cleanupScheduled) { + return; + } + + _cleanupScheduled = YES; + + // Cleanup NSStream delegate's in the same RunLoop used by the streams themselves: + // This way we'll prevent race conditions between handleEvent and SRWebsocket's dealloc + NSTimer *timer = [NSTimer timerWithTimeInterval:(0.0f) target:self selector:@selector(_cleanupSelfReference:) userInfo:nil repeats:NO]; + [[NSRunLoop FSR_networkRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; + } +} + +- (void)_cleanupSelfReference:(NSTimer *)timer +{ + @synchronized(self) { + // Nuke NSStream delegate's + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + // Remove the streams, right now, from the networkRunLoop + [_inputStream close]; + [_outputStream close]; + } + + // Cleanup selfRetain in the same GCD queue as usual + dispatch_async(_workQueue, ^{ + self->_selfRetain = nil; + }); +} + + +static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'}; + +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; +{ + [self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler]; +} + +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +{ + // TODO optimize so this can continue from where we last searched + stream_scanner consumer = ^size_t(NSData *data) { + __block size_t found_size = 0; + __block size_t match_count = 0; + + size_t size = data.length; + const unsigned char *buffer = data.bytes; + for (int i = 0; i < size; i++ ) { + if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) { + match_count += 1; + if (match_count == length) { + found_size = i + 1; + break; + } + } else { + match_count = 0; + } + } + return found_size; + }; + [self _addConsumerWithScanner:consumer callback:dataHandler]; +} + + +// Returns true if did work +- (BOOL)_innerPumpScanner { + + BOOL didWork = NO; + + if (self.readyState >= SR_CLOSING) { + return didWork; + } + + if (!_consumers.count) { + return didWork; + } + + size_t curSize = _readBuffer.length - _readBufferOffset; + if (!curSize) { + return didWork; + } + + FSRIOConsumer *consumer = [_consumers objectAtIndex:0]; + + size_t bytesNeeded = consumer.bytesNeeded; + + size_t foundSize = 0; + if (consumer.consumer) { + NSData *tempView = [NSData dataWithBytesNoCopy:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset freeWhenDone:NO]; + foundSize = consumer.consumer(tempView); + } else { + assert(consumer.bytesNeeded); + if (curSize >= bytesNeeded) { + foundSize = bytesNeeded; + } else if (consumer.readToCurrentFrame) { + foundSize = curSize; + } + } + + NSData *slice = nil; + if (consumer.readToCurrentFrame || foundSize) { + NSRange sliceRange = NSMakeRange(_readBufferOffset, foundSize); + slice = [_readBuffer subdataWithRange:sliceRange]; + + _readBufferOffset += foundSize; + + if (_readBufferOffset > 4096 && _readBufferOffset > (_readBuffer.length >> 1)) { + _readBuffer = [[NSMutableData alloc] initWithBytes:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset]; _readBufferOffset = 0; + } + + if (consumer.unmaskBytes) { + NSMutableData *mutableSlice = [slice mutableCopy]; + + NSUInteger len = mutableSlice.length; + uint8_t *bytes = mutableSlice.mutableBytes; + + for (int i = 0; i < len; i++) { + bytes[i] = bytes[i] ^ _currentReadMaskKey[_currentReadMaskOffset % sizeof(_currentReadMaskKey)]; + _currentReadMaskOffset += 1; + } + + slice = mutableSlice; + } + + if (consumer.readToCurrentFrame) { + [_currentFrameData appendData:slice]; + + _readOpCount += 1; + + if (_currentFrameOpcode == SROpCodeTextFrame) { + // Validate UTF8 stuff. + size_t currentDataSize = _currentFrameData.length; + if (_currentFrameOpcode == SROpCodeTextFrame && currentDataSize > 0) { + // TODO: Optimize the crap out of this. Don't really have to copy all the data each time + + size_t scanSize = currentDataSize - _currentStringScanPosition; + + NSData *scan_data = [_currentFrameData subdataWithRange:NSMakeRange(_currentStringScanPosition, scanSize)]; + int32_t valid_utf8_size = validate_dispatch_data_partial_string(scan_data); + + if (valid_utf8_size == -1) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + return didWork; + } else { + _currentStringScanPosition += valid_utf8_size; + } + } + + } + + consumer.bytesNeeded -= foundSize; + + if (consumer.bytesNeeded == 0) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, nil); + didWork = YES; + } + } else if (foundSize) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, slice); + didWork = YES; + } + } + return didWork; +} + +-(void)_pumpScanner; +{ + [self assertOnWorkQueue]; + + if (!_isPumping) { + _isPumping = YES; + } else { + return; + } + + while ([self _innerPumpScanner]) { + + } + + _isPumping = NO; +} + +//#define NOMASK + +static const size_t SRFrameHeaderOverhead = 32; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; +{ + [self assertOnWorkQueue]; + + if (data == nil) { + return; + } + + NSAssert([data isKindOfClass:[NSData class]] || [data isKindOfClass:[NSString class]], @"Function expects nil, NSString or NSData"); + + size_t payloadLength = [data isKindOfClass:[NSString class]] ? [(NSString *)data lengthOfBytesUsingEncoding:NSUTF8StringEncoding] : [data length]; + + NSMutableData *frame = [[NSMutableData alloc] initWithLength:payloadLength + SRFrameHeaderOverhead]; + if (!frame) { + [self closeWithCode:SRStatusCodeMessageTooBig reason:@"Message too big"]; + return; + } + uint8_t *frame_buffer = (uint8_t *)[frame mutableBytes]; + + // set fin + frame_buffer[0] = SRFinMask | opcode; + + BOOL useMask = YES; +#ifdef NOMASK + useMask = NO; +#endif + + if (useMask) { + // set the mask and header + frame_buffer[1] |= SRMaskMask; + } + + size_t frame_buffer_size = 2; + + const uint8_t *unmasked_payload = NULL; + if ([data isKindOfClass:[NSData class]]) { + unmasked_payload = (uint8_t *)[data bytes]; + } else if ([data isKindOfClass:[NSString class]]) { + unmasked_payload = (const uint8_t *)[data UTF8String]; + } else { + assert(NO); + } + + if (payloadLength < 126) { + frame_buffer[1] |= payloadLength; + } else if (payloadLength <= UINT16_MAX) { + frame_buffer[1] |= 126; + *((uint16_t *)(frame_buffer + frame_buffer_size)) = EndianU16_BtoN((uint16_t)payloadLength); + frame_buffer_size += sizeof(uint16_t); + } else { + frame_buffer[1] |= 127; + *((uint64_t *)(frame_buffer + frame_buffer_size)) = EndianU64_BtoN((uint64_t)payloadLength); + frame_buffer_size += sizeof(uint64_t); + } + + if (!useMask) { + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i]; + frame_buffer_size += 1; + } + } else { + uint8_t *mask_key = frame_buffer + frame_buffer_size; + int result = SecRandomCopyBytes(kSecRandomDefault, sizeof(uint32_t), (uint8_t *)mask_key); + assert(result == 0); + frame_buffer_size += sizeof(uint32_t); + + // TODO: could probably optimize this with SIMD + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i] ^ mask_key[i % sizeof(uint32_t)]; + frame_buffer_size += 1; + } + } + + assert(frame_buffer_size <= [frame length]); + frame.length = frame_buffer_size; + + [self _writeData:frame]; +} + +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode; +{ + __weak __typeof__(self) weakSelf = self; + + // turn on keep-alive for the output stream. + if (eventCode == NSStreamEventOpenCompleted && aStream == _outputStream) { + CFDataRef socketData = CFWriteStreamCopyProperty((CFWriteStreamRef)_outputStream, kCFStreamPropertySocketNativeHandle); + // In rare cases socketData might be nil (there are crash reports out there), in which case we'll have to just + // live without keep-alive :( + if (socketData != nil) { + CFSocketNativeHandle socket; + CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket); + CFRelease(socketData); + + int keepAliveOn = 1; + if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepAliveOn, sizeof(keepAliveOn)) == -1) { + SRFastLog(@"Failed to turn on TCP keepalive for websocket"); + } + } + } + + if (_secure && !_pinnedCertFound && (eventCode == NSStreamEventHasBytesAvailable || eventCode == NSStreamEventHasSpaceAvailable)) { + + NSArray *sslCerts = [_urlRequest FSR_SSLPinnedCertificates]; + if (sslCerts) { + SecTrustRef secTrust = (__bridge SecTrustRef)[aStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust]; + if (secTrust) { + NSInteger numCerts = SecTrustGetCertificateCount(secTrust); + for (NSInteger i = 0; i < numCerts && !_pinnedCertFound; i++) { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrust, i); + NSData *certData = CFBridgingRelease(SecCertificateCopyData(cert)); + + for (id ref in sslCerts) { + SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref; + NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert)); + + if ([trustedCertData isEqualToData:certData]) { + _pinnedCertFound = YES; + break; + } + } + } + } + + if (!_pinnedCertFound) { + dispatch_async(_workQueue, ^{ + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"Invalid server cert" }; + [weakSelf _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:23556 userInfo:userInfo]]; + }); + return; + } + } + } + + // SRFastLog(@"%@ Got stream event %d", aStream, eventCode); + dispatch_async(_workQueue, ^{ + [weakSelf safeHandleEvent:eventCode stream:aStream]; + }); +} + +- (void)safeHandleEvent:(NSStreamEvent)eventCode stream:(NSStream *)aStream +{ + switch (eventCode) { + case NSStreamEventOpenCompleted: { + SRFastLog(@"NSStreamEventOpenCompleted %@", aStream); + if (self.readyState >= SR_CLOSING) { + return; + } + + + assert(_readBuffer); + + if (self.readyState == SR_CONNECTING && aStream == _inputStream) { + [self didConnect]; + } + [self _pumpWriting]; + [self _pumpScanner]; + break; + } + + case NSStreamEventErrorOccurred: { + // Note: The upstream code for SocketRocket logs the error message, but this causes + // crashes on iOS 13 (https://github.com/firebase/firebase-ios-sdk/issues/3950) + SRFastLog(@"NSStreamEventErrorOccurred %@", aStream); + /// TODO specify error better! + [self _failWithError:aStream.streamError]; + _readBufferOffset = 0; + [_readBuffer setLength:0]; + break; + + } + + case NSStreamEventEndEncountered: { + [self _pumpScanner]; + SRFastLog(@"NSStreamEventEndEncountered %@", aStream); + if (aStream.streamError) { + [self _failWithError:aStream.streamError]; + } else { + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self.readyState = SR_CLOSED; + [self _scheduleCleanup]; + } + + if (!self->_sentClose && !self->_failed) { + self->_sentClose = YES; + // If we get closed in this state it's probably not clean because we should be sending this when we send messages + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:0 reason:@"Stream end encountered" wasClean:NO]; + } + }]; + } + }); + } + + break; + } + + case NSStreamEventHasBytesAvailable: { + SRFastLog(@"NSStreamEventHasBytesAvailable %@", aStream); + const NSUInteger bufferSize = 2048; + uint8_t buffer[bufferSize]; + + while (_inputStream.hasBytesAvailable) { + NSInteger bytes_read = [_inputStream read:buffer maxLength:bufferSize]; + + if (bytes_read > 0) { + [_readBuffer appendBytes:buffer length:bytes_read]; + } else if (bytes_read < 0) { + [self _failWithError:_inputStream.streamError]; + } + + if (bytes_read != bufferSize) { + break; + } + }; + [self _pumpScanner]; + break; + } + + case NSStreamEventHasSpaceAvailable: { + SRFastLog(@"NSStreamEventHasSpaceAvailable %@", aStream); + [self _pumpWriting]; + break; + } + + default: + SRFastLog(@"(default) %@", aStream); + break; + } +} + +@end + + +@implementation FSRIOConsumer + +@synthesize bytesNeeded = _bytesNeeded; +@synthesize consumer = _scanner; +@synthesize handler = _handler; +@synthesize readToCurrentFrame = _readToCurrentFrame; +@synthesize unmaskBytes = _unmaskBytes; + +- (void)setupWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + _scanner = [scanner copy]; + _handler = [handler copy]; + _bytesNeeded = bytesNeeded; + _readToCurrentFrame = readToCurrentFrame; + _unmaskBytes = unmaskBytes; + assert(_scanner || _bytesNeeded); +} + +@end + +@implementation FSRIOConsumerPool { + NSUInteger _poolSize; + NSMutableArray *_bufferedConsumers; +} + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; +{ + self = [super init]; + if (self) { + _poolSize = poolSize; + _bufferedConsumers = [[NSMutableArray alloc] initWithCapacity:poolSize]; + } + return self; +} + +- (id)init +{ + return [self initWithBufferCapacity:8]; +} + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + FSRIOConsumer *consumer = nil; + if (_bufferedConsumers.count) { + consumer = [_bufferedConsumers lastObject]; + [_bufferedConsumers removeLastObject]; + } else { + consumer = [[FSRIOConsumer alloc] init]; + } + + [consumer setupWithScanner:scanner handler:handler bytesNeeded:bytesNeeded readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]; + + return consumer; +} + +- (void)returnConsumer:(FSRIOConsumer *)consumer; +{ + if (_bufferedConsumers.count < _poolSize) { + [_bufferedConsumers addObject:consumer]; + } +} + +@end + +@implementation NSURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSMutableURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +- (void)setFSR_SSLPinnedCertificates:(NSArray *)FSR_SSLPinnedCertificates; +{ + [NSURLProtocol setProperty:FSR_SSLPinnedCertificates forKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSURL (FSRWebSocket) + +- (NSString *)SR_origin; +{ + NSString *scheme = [self.scheme lowercaseString]; + + if ([scheme isEqualToString:@"wss"]) { + scheme = @"https"; + } else if ([scheme isEqualToString:@"ws"]) { + scheme = @"http"; + } + + if (self.port != nil) { + return [NSString stringWithFormat:@"%@://%@:%@/", scheme, self.host, self.port]; + } else { + return [NSString stringWithFormat:@"%@://%@/", scheme, self.host]; + } +} + +@end + +// #define SR_ENABLE_LOG + +static inline void SRFastLog(NSString *format, ...) { +#ifdef SR_ENABLE_LOG + __block va_list arg_list; + va_start (arg_list, format); + + NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list]; + + va_end(arg_list); + + NSLog(@"[SR] %@", formattedString); +#endif +} + + +#ifdef HAS_ICU + +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + + const void * contents = [data bytes]; + long size = [data length]; + + const uint8_t *str = (const uint8_t *)contents; + + + UChar32 codepoint = 1; + int32_t offset = 0; + int32_t lastOffset = 0; + while(offset < size && codepoint > 0) { + lastOffset = offset; + U8_NEXT(str, offset, size, codepoint); + } + + if (codepoint == -1) { + // Check to see if the last byte is valid or whether it was just continuing + if (!U8_IS_LEAD(str[lastOffset]) || U8_COUNT_TRAIL_BYTES(str[lastOffset]) + lastOffset < (int32_t)size) { + + size = -1; + } else { + uint8_t leadByte = str[lastOffset]; + U8_MASK_LEAD_BYTE(leadByte, U8_COUNT_TRAIL_BYTES(leadByte)); + + for (int i = lastOffset + 1; i < offset; i++) { + + if (U8_IS_SINGLE(str[i]) || U8_IS_LEAD(str[i]) || !U8_IS_TRAIL(str[i])) { + size = -1; + } + } + + if (size != -1) { + size = lastOffset; + } + } + } + + if (size != -1 && ![[NSString alloc] initWithBytesNoCopy:(char *)[data bytes] length:size encoding:NSUTF8StringEncoding freeWhenDone:NO]) { + size = -1; + } + + return (int32_t)size; +} + +#else + +// This is a hack, and probably not optimal +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + static const int maxCodepointSize = 3; + + for (int i = 0; i < maxCodepointSize; i++) { + NSString *str = [[NSString alloc] initWithBytesNoCopy:(char *)data.bytes length:data.length - i encoding:NSUTF8StringEncoding freeWhenDone:NO]; + if (str) { + return (int)(data.length - i); + } + } + + return -1; +} + +#endif + +static _FSRRunLoopThread *networkThread = nil; +static NSRunLoop *networkRunLoop = nil; + +@implementation NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + networkThread = [[_FSRRunLoopThread alloc] init]; + networkThread.name = @"com.squareup.SocketRocket.NetworkThread"; + [networkThread start]; + networkRunLoop = networkThread.runLoop; + }); + + return networkRunLoop; +} + +@end + + +@implementation _FSRRunLoopThread { + dispatch_group_t _waitGroup; +} + +@synthesize runLoop = _runLoop; + +- (void)dealloc +{ + sr_dispatch_release(_waitGroup); +} + +- (id)init +{ + self = [super init]; + if (self) { + _waitGroup = dispatch_group_create(); + dispatch_group_enter(_waitGroup); + } + return self; +} + + +/** + * This is the main method of the thread on which the socket events are scheduled in a run loop. + */ +- (void)main; +{ + @autoreleasepool { + _runLoop = [NSRunLoop currentRunLoop]; + dispatch_group_leave(_waitGroup); + + // Add an empty run loop source to prevent runloop from spinning. + CFRunLoopSourceContext sourceCtx = { + .version = 0, + .info = NULL, + .retain = NULL, + .release = NULL, + .copyDescription = NULL, + .equal = NULL, + .hash = NULL, + .schedule = NULL, + .cancel = NULL, + .perform = NULL + }; + CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + CFRelease(source); + + while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { + + } + assert(NO); + } +} + +- (NSRunLoop *)runLoop; +{ + dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER); + return _runLoop; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h new file mode 100644 index 00000000..bac393bc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h @@ -0,0 +1,23 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface FSRUtilities : NSObject + ++ (NSString *)base64EncodedStringFromData:(NSData *)data; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m new file mode 100644 index 00000000..2be1d842 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m @@ -0,0 +1,37 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "NSData+SRB64Additions.h" +#import "fbase64.h" + +@implementation FSRUtilities + ++ (NSString *)base64EncodedStringFromData:(NSData *)data { + size_t buffer_size = ((data.length * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(data.bytes, data.length, buffer, buffer_size); + + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSUTF8StringEncoding freeWhenDone:YES]; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c new file mode 100644 index 00000000..238c23cf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c @@ -0,0 +1,318 @@ +/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ + + +// +// Distributed with modifications by Firebase ( https://www.firebase.com ) +// + +#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "fbase64.h" + +static const char Base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) +int +f_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + u_int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int)(datalength); +} +#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ + +#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +f_b64_pton(char const *src, u_char *target, size_t targsize) +{ + u_int tarindex, state; + int ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + +#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h new file mode 100644 index 00000000..a9bf1427 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h @@ -0,0 +1,33 @@ +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FSocketRocket_base64_h +#define FSocketRocket_base64_h + +#include + +extern int +f_b64_ntop(u_char const *src, + size_t srclength, + char *target, + size_t targsize); + +extern int +f_b64_pton(char const *src, + u_char *target, + size_t targsize); + + +#endif diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h new file mode 100644 index 00000000..c0baa224 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h @@ -0,0 +1,105 @@ +// +// APLevelDB.h +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +extern NSString * const APLevelDBErrorDomain; + +@class APLevelDBIterator; +@protocol APLevelDBWriteBatch; + +@interface APLevelDB : NSObject + +@property (nonatomic, readonly, strong) NSString *path; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing*)errorOut; +- (void)close; + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key; +- (BOOL)setString:(NSString *)str forKey:(NSString *)key; + +- (NSData *)dataForKey:(NSString *)key; +- (NSString *)stringForKey:(NSString *)key; + +- (BOOL)removeKey:(NSString *)key; + +- (NSArray *)allKeys; + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix usingBlock:(void (^)(NSString *key, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to; +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to; + +// Objective-C Subscripting Support: +// The database object supports subscripting for string-string and string-data key-value access and assignment. +// Examples: +// db[@"key"] = @"value"; +// db[@"key"] = [NSData data]; +// NSString *s = db[@"key"]; +// An NSInvalidArgumentException is raised if the key is not an NSString, or if the assigned object is not an +// instance of NSString or NSData. +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; + +// Batch write/atomic update support: +- (id)beginWriteBatch; + +@end + + +@interface APLevelDBIterator : NSObject + ++ (id)iteratorWithLevelDB:(APLevelDB *)db; + +// Designated initializer: +- (id)initWithLevelDB:(APLevelDB *)db; + +- (BOOL)seekToKey:(NSString *)key; +- (NSString *)nextKey; +- (NSString *)key; +- (NSString *)valueAsString; +- (NSData *)valueAsData; + +@end + + +@protocol APLevelDBWriteBatch + +- (void)setData:(NSData *)data forKey:(NSString *)key; +- (void)setString:(NSString *)str forKey:(NSString *)key; + +- (void)removeKey:(NSString *)key; + +// Remove all of the buffered sets and removes: +- (void)clear; +- (BOOL)commit; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm new file mode 100644 index 00000000..cdecce68 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm @@ -0,0 +1,500 @@ +// +// APLevelDB.m +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +// Portions of APLevelDB are based on LevelDB-ObjC: +// https://github.com/hoisie/LevelDB-ObjC +// Specifically the SliceFromString/StringFromSlice macros, and the structure of +// the enumeration methods. License for those potions follows: +// +// Copyright (c) 2011 Pave Labs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "APLevelDB.h" + +#import "leveldb/db.h" +#import "leveldb/options.h" +#import "leveldb/write_batch.h" + +NSString * const APLevelDBErrorDomain = @"APLevelDBErrorDomain"; + +#define SliceFromString(_string_) (leveldb::Slice((char *)[_string_ UTF8String], [_string_ lengthOfBytesUsingEncoding:NSUTF8StringEncoding])) +#define StringFromSlice(_slice_) ([[NSString alloc] initWithBytes:_slice_.data() length:_slice_.size() encoding:NSUTF8StringEncoding]) + + +@interface APLevelDBWriteBatch : NSObject { + @package + leveldb::WriteBatch _batch; +} + +@property (nonatomic, strong) APLevelDB *levelDB; + +- (id)initWithLevelDB:(APLevelDB *)levelDB; +@end + + +#pragma mark - APLevelDB + +@interface APLevelDB () { + leveldb::DB *_db; + leveldb::ReadOptions _readOptions; + leveldb::WriteOptions _writeOptions; +} +- (id)initWithPath:(NSString *)path error:(NSError **)errorOut; ++ (leveldb::Options)defaultCreateOptions; +@property (nonatomic, readonly) leveldb::DB *db; +@end + + +@implementation APLevelDB + +@synthesize path = _path; +@synthesize db = _db; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + return [[APLevelDB alloc] initWithPath:path error:errorOut]; +} + +- (id)initWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + if ((self = [super init])) + { + _path = path; + + leveldb::Options options = [[self class] defaultCreateOptions]; + + leveldb::Status status = leveldb::DB::Open(options, [_path UTF8String], &_db); + + if (!status.ok()) + { + if (errorOut) + { + NSString *statusString = [[NSString alloc] initWithCString:status.ToString().c_str() encoding:NSUTF8StringEncoding]; + *errorOut = [NSError errorWithDomain:APLevelDBErrorDomain + code:0 + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:statusString, NSLocalizedDescriptionKey, nil]]; + } + return nil; + } + + _writeOptions.sync = false; + } + return self; +} + +- (void)close { + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + +- (void)dealloc +{ + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + ++ (leveldb::Options)defaultCreateOptions +{ + leveldb::Options options; + options.create_if_missing = true; + return options; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (BOOL)setString:(NSString *)str forKey:(NSString *)key +{ + // This could have been based on + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (NSData *)dataForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + if (!status.ok()) + return nil; + else + return [NSData dataWithBytes:valueCPPString.data() length:valueCPPString.size()]; +} + +- (NSString *)stringForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + // We assume (dangerously?) UTF-8 string encoding: + if (!status.ok()) + return nil; + else + return [[NSString alloc] initWithBytes:valueCPPString.data() length:valueCPPString.size() encoding:NSUTF8StringEncoding]; +} + +- (BOOL)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Status status = _db->Delete(_writeOptions, keySlice); + return (status.ok() == true); +} + +- (NSArray *)allKeys +{ + NSMutableArray *keys = [NSMutableArray array]; + [self enumerateKeys:^(NSString *key, BOOL *stop) { + [keys addObject:key]; + }]; + return keys; +} + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asStrings:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asStrings:(void (^)(NSString *, NSString *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSString *v = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding]; + block(k, v, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" usingBlock:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString usingBlock:(void (^)(NSString *key, BOOL *stop))block; +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Slice prefix = SliceFromString(prefixString); + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + block(k, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *data, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asData:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asData:(void (^)(NSString *, NSData *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSData *data = [NSData dataWithBytes:value.data() length:value.size()]; + block(k, data, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to { + NSUInteger size = 0; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + iter->Seek(fromSlice); + while (iter->Valid() && iter->key().compare(toSlice) <= 0) { + size += iter->value().size(); + iter->Next(); + } + delete iter; + return size; +} + + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to { + leveldb::Range ranges[1]; + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + ranges[0] = leveldb::Range(fromSlice, toSlice); + uint64_t sizes[1]; + _db->GetApproximateSizes(ranges, 1, sizes); + return (NSUInteger)sizes[0]; +} + +#pragma mark - Subscripting Support + +- (id)objectForKeyedSubscript:(id)key +{ + if (![key respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be an NSString"]; + } + return [self stringForKey:key]; +} +- (void)setObject:(id)thing forKeyedSubscript:(id)key +{ + id idKey = (id) key; + if (![idKey respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be NSString or NSData"]; + } + + if ([thing respondsToSelector:@selector(componentsSeparatedByString:)]) + [self setString:thing forKey:(NSString *)key]; + else if ([thing respondsToSelector:@selector(subdataWithRange:)]) + [self setData:thing forKey:(NSString *)key]; + else + [NSException raise:NSInvalidArgumentException format:@"object must be NSString or NSData"]; +} + +#pragma mark - Atomic Updates + +- (id)beginWriteBatch +{ + APLevelDBWriteBatch *batch = [[APLevelDBWriteBatch alloc] initWithLevelDB:self]; + return batch; +} + +- (BOOL)commitWriteBatch:(id)theBatch +{ + if (!theBatch) + return NO; + + APLevelDBWriteBatch *batch = theBatch; + + leveldb::Status status; + status = _db->Write(_writeOptions, &batch->_batch); + return (status.ok() == true); +} + +@end + + +#pragma mark - APLevelDBIterator + +@interface APLevelDBIterator () { + leveldb::Iterator *_iter; +} + +@property (nonatomic, strong) APLevelDB *levelDB; +@end + + + +@implementation APLevelDBIterator + ++ (id)iteratorWithLevelDB:(APLevelDB *)db +{ + APLevelDBIterator *iter = [[[self class] alloc] initWithLevelDB:db]; + return iter; +} + +- (id)initWithLevelDB:(APLevelDB *)db +{ + if ((self = [super init])) + { + // Hold on to the database so it doesn't get deallocated before the iterator is deallocated + self->_levelDB = db; + _iter = db.db->NewIterator(leveldb::ReadOptions()); + _iter->SeekToFirst(); + if (!_iter->Valid()) + return nil; + } + return self; +} + +- (id)init +{ + [NSException raise:@"BadInitializer" format:@"Use the designated initializer, -initWithLevelDB:, instead."]; + return nil; +} + +- (void)dealloc +{ + self->_levelDB = nil; + delete _iter; + _iter = NULL; +} + +- (BOOL)seekToKey:(NSString *)key +{ + leveldb::Slice target = SliceFromString(key); + _iter->Seek(target); + return _iter->Valid() == true; +} + +- (void)seekToFirst +{ + _iter->SeekToFirst(); +} + +- (void)seekToLast +{ + _iter->SeekToLast(); +} + +- (NSString *)nextKey +{ + _iter->Next(); + return [self key]; +} + +- (NSString *)key +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->key(); + return StringFromSlice(value); +} + +- (NSString *)valueAsString +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return StringFromSlice(value); +} + +- (NSData *)valueAsData +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return [NSData dataWithBytes:value.data() length:value.size()]; +} + +@end + + + +#pragma mark - APLevelDBWriteBatch + +@implementation APLevelDBWriteBatch + +- (id)initWithLevelDB:(APLevelDB *)levelDB { + self = [super init]; + if (self != nil) { + self->_levelDB = levelDB; + } + return self; +} + +- (void)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + _batch.Put(keySlice, valueSlice); +} +- (void)setString:(NSString *)str forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + _batch.Put(keySlice, valueSlice); +} + +- (void)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + _batch.Delete(keySlice); +} + +- (void)clear +{ + _batch.Clear(); +} + +- (BOOL)commit { + return [self.levelDB commitWriteBatch:self]; +} + +@end + diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRAppInternal.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponent.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentContainer.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentType.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRDependency.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrorCode.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrors.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLibrary.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLogger.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIROptionsInternal.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/MyExperiences copy/Pods/FirebaseDatabase/Interop/Auth/Public/FIRAuthInterop.h b/MyExperiences copy/Pods/FirebaseDatabase/Interop/Auth/Public/FIRAuthInterop.h new file mode 100644 index 00000000..a33da7c9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/Interop/Auth/Public/FIRAuthInterop.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRAuthInterop_h +#define FIRAuthInterop_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRTokenCallback + @brief The type of block which gets called when a token is ready. + */ +typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(TokenCallback); + +/// Common methods for Auth interoperability. +NS_SWIFT_NAME(AuthInterop) +@protocol FIRAuthInterop + +/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired. +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback; + +/// Get the current Auth user's UID. Returns nil if there is no user signed in. +- (nullable NSString *)getUserID; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRAuthInterop_h */ diff --git a/MyExperiences copy/Pods/FirebaseDatabase/LICENSE b/MyExperiences copy/Pods/FirebaseDatabase/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseDatabase/README.md b/MyExperiences copy/Pods/FirebaseDatabase/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseDatabase/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h new file mode 100644 index 00000000..5bc21a11 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class FIRInstallationsHTTPError; + +NS_ASSUME_NONNULL_BEGIN + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer); + +@interface FIRInstallationsErrorUtil : NSObject + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception; ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error; + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status; + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName; + ++ (NSError *)JSONSerializationError:(NSError *)error; + ++ (NSError *)networkErrorWithError:(NSError *)error; + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName; + ++ (NSError *)corruptedIIDTokenData; + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data; ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode; + +/** + * Returns the passed error if it is already in the public domain or a new error with the passed + * error at `NSUnderlyingErrorKey`. + */ ++ (NSError *)publicDomainErrorWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m new file mode 100644 index 00000000..f85923ac --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m @@ -0,0 +1,124 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsErrorUtil.h" + +#import "FIRInstallationsHTTPError.h" + +NSString *const kFirebaseInstallationsErrorDomain = @"com.firebase.installations"; + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer) { + if (pointer != NULL) { + *pointer = error; + } +} + +@implementation FIRInstallationsErrorUtil + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"NSKeyedArchiver error."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:error]; +} + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status { + NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeKeychain + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *failureReason = + [NSString stringWithFormat:@"Installation for appID %@ appName %@ not found", appID, appName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)corruptedIIDTokenData { + NSString *failureReason = + @"IID token data stored in Keychain is corrupted or in an incompatible format."; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:HTTPResponse data:data]; +} + ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + return [(FIRInstallationsHTTPError *)error HTTPResponse].statusCode == HTTPCode; +} + ++ (NSError *)JSONSerializationError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"Failed to serialize JSON data."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName { + NSString *failureReason = [NSString + stringWithFormat:@"A required response field with name %@ is missing", missingFieldName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)networkErrorWithError:(NSError *)error { + return [self installationsErrorWithCode:FIRInstallationsErrorCodeServerUnreachable + failureReason:@"Network connection error." + underlyingError:error]; +} + ++ (NSError *)publicDomainErrorWithError:(NSError *)error { + if ([error.domain isEqualToString:kFirebaseInstallationsErrorDomain]) { + return error; + } + + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:nil + underlyingError:error]; +} + ++ (NSError *)installationsErrorWithCode:(FIRInstallationsErrorCode)code + failureReason:(nullable NSString *)failureReason + underlyingError:(nullable NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + userInfo[NSUnderlyingErrorKey] = underlyingError; + userInfo[NSLocalizedFailureReasonErrorKey] = failureReason; + + return [NSError errorWithDomain:kFirebaseInstallationsErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h new file mode 100644 index 00000000..ad0eb8c1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Represents an error caused by an unexpected API response. */ +@interface FIRInstallationsHTTPError : NSError + +@property(nonatomic, readonly) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic, readonly, nonnull) NSData *data; + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse data:(nullable NSData *)data; + +@end + +NS_ASSUME_NONNULL_END + +typedef NS_ENUM(NSInteger, FIRInstallationsHTTPCodes) { + FIRInstallationsHTTPCodesTooManyRequests = 429, + FIRInstallationsHTTPCodesServerInternalError = 500, +}; + +/** Possible response HTTP codes for `CreateInstallation` API request. */ +typedef NS_ENUM(NSInteger, FIRInstallationsRegistrationHTTPCode) { + FIRInstallationsRegistrationHTTPCodeSuccess = 201, + FIRInstallationsRegistrationHTTPCodeInvalidArgument = 400, + FIRInstallationsRegistrationHTTPCodeInvalidAPIKey = 401, + FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch = 403, + FIRInstallationsRegistrationHTTPCodeProjectNotFound = 404, + FIRInstallationsRegistrationHTTPCodeTooManyRequests = 429, + FIRInstallationsRegistrationHTTPCodeServerInternalError = 500 +}; + +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenHTTPCode) { + FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication = 401, + FIRInstallationsAuthTokenHTTPCodeFIDNotFound = 404, +}; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m new file mode 100644 index 00000000..05256ea1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsErrorUtil.h" + +@implementation FIRInstallationsHTTPError + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSDictionary *userInfo = [FIRInstallationsHTTPError userInfoWithHTTPResponse:HTTPResponse + data:data]; + self = [super + initWithDomain:kFirebaseInstallationsErrorDomain + code:[FIRInstallationsHTTPError errorCodeWithHTTPCode:HTTPResponse.statusCode] + userInfo:userInfo]; + if (self) { + _HTTPResponse = HTTPResponse; + _data = data; + } + return self; +} + ++ (FIRInstallationsErrorCode)errorCodeWithHTTPCode:(NSInteger)HTTPCode { + return FIRInstallationsErrorCodeUnknown; +} + ++ (NSDictionary *)userInfoWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSString *failureReason = + [NSString stringWithFormat:@"The server responded with an error: \n - URL: %@ \n - HTTP " + @"status code: %ld \n - Response body: %@", + HTTPResponse.URL, (long)HTTPResponse.statusCode, responseString]; + return @{NSLocalizedFailureReasonErrorKey : failureReason}; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:self.HTTPResponse data:self.data]; +} + +#pragma mark - NSSecureCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)coder { + NSHTTPURLResponse *HTTPResponse = [coder decodeObjectOfClass:[NSHTTPURLResponse class] + forKey:@"HTTPResponse"]; + if (!HTTPResponse) { + return nil; + } + NSData *data = [coder decodeObjectOfClass:[NSData class] forKey:@"data"]; + + return [self initWithHTTPResponse:HTTPResponse data:data]; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.HTTPResponse forKey:@"HTTPResponse"]; + [coder encodeObject:self.data forKey:@"data"]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m new file mode 100644 index 00000000..d508663e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m @@ -0,0 +1,245 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FIRInstallationsAuthTokenResultInternal.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIDController.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsVersion.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol FIRInstallationsInstanceProvider +@end + +@interface FIRInstallations () +@property(nonatomic, readonly) FIROptions *appOptions; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsIDController *installationsIDController; + +@end + +@implementation FIRInstallations + +#pragma mark - Firebase component + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-install" + withVersion:[NSString stringWithUTF8String:FIRInstallationsVersionStr]]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + FIRInstallations *installations = [[FIRInstallations alloc] initWithApp:container.app]; + return installations; + }; + + FIRComponent *installationsProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstallationsInstanceProvider) + instantiationTiming:FIRInstantiationTimingAlwaysEager + dependencies:@[] + creationBlock:creationBlock]; + return @[ installationsProvider ]; +} + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWitAppOptions:app.options appName:app.name]; +} + +- (instancetype)initWitAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + FIRInstallationsIDController *IDController = + [[FIRInstallationsIDController alloc] initWithGoogleAppID:appOptions.googleAppID + appName:appName + APIKey:appOptions.APIKey + projectID:appOptions.projectID + GCMSenderID:appOptions.GCMSenderID + accessGroup:appOptions.appGroupID]; + + // `prefetchAuthToken` is disabled due to b/156746574. + return [self initWithAppOptions:appOptions + appName:appName + installationsIDController:IDController + prefetchAuthToken:NO]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithAppOptions:(FIROptions *)appOptions + appName:(NSString *)appName + installationsIDController:(FIRInstallationsIDController *)installationsIDController + prefetchAuthToken:(BOOL)prefetchAuthToken { + self = [super init]; + if (self) { + [[self class] validateAppOptions:appOptions appName:appName]; + [[self class] assertCompatibleIIDVersion]; + + _appOptions = [appOptions copy]; + _appName = [appName copy]; + _installationsIDController = installationsIDController; + + // Pre-fetch auth token. + if (prefetchAuthToken) { + [self authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error){ + }]; + } + } + return self; +} + ++ (void)validateAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + NSMutableArray *missingFields = [NSMutableArray array]; + if (appName.length < 1) { + [missingFields addObject:@"`FirebaseApp.name`"]; + } + if (appOptions.APIKey.length < 1) { + [missingFields addObject:@"`FirebaseOptions.APIKey`"]; + } + if (appOptions.googleAppID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.googleAppID`"]; + } + + // TODO(#4692): Check for `appOptions.projectID.length < 1` only. + // We can use `GCMSenderID` instead of `projectID` temporary. + if (appOptions.projectID.length < 1 && appOptions.GCMSenderID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.projectID`"]; + } + + if (missingFields.count > 0) { + [NSException + raise:kFirebaseInstallationsErrorDomain + format: + @"%@[%@] Could not configure Firebase Installations due to invalid FirebaseApp " + @"options. The following parameters are nil or empty: %@. If you use " + @"GoogleServices-Info.plist please download the most recent version from the Firebase " + @"Console. If you configure Firebase in code, please make sure you specify all " + @"required parameters.", + kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseAppOptions, + [missingFields componentsJoinedByString:@", "]]; + } +} + +#pragma mark - Public + ++ (FIRInstallations *)installations { + FIRApp *defaultApp = [FIRApp defaultApp]; + if (!defaultApp) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"The default FirebaseApp instance must be configured before the default" + @"FirebaseApp instance can be initialized. One way to ensure that is to " + @"call `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) in the App" + @" Delegate's `application:didFinishLaunchingWithOptions:` " + @"(`application(_:didFinishLaunchingWithOptions:)` in Swift)."]; + } + + return [self installationsWithApp:defaultApp]; +} + ++ (FIRInstallations *)installationsWithApp:(FIRApp *)app { + id installations = + FIR_COMPONENT(FIRInstallationsInstanceProvider, app.container); + return (FIRInstallations *)installations; +} + +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion { + [self.installationsIDController getInstallationItem] + .then(^id(FIRInstallationsItem *installation) { + completion(installation.firebaseInstallationID, nil); + return nil; + }) + .catch(^(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion { + [self authTokenForcingRefresh:NO completion:completion]; +} + +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion { + [self.installationsIDController getAuthTokenForcingRefresh:forceRefresh] + .then(^FIRInstallationsAuthTokenResult *(FIRInstallationsItem *installation) { + FIRInstallationsAuthTokenResult *result = [[FIRInstallationsAuthTokenResult alloc] + initWithToken:installation.authToken.token + expirationDate:installation.authToken.expirationDate]; + return result; + }) + .then(^id(FIRInstallationsAuthTokenResult *token) { + completion(token, nil); + return nil; + }) + .catch(^void(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion { + [self.installationsIDController deleteInstallation] + .then(^id(id result) { + completion(nil); + return nil; + }) + .catch(^void(NSError *error) { + completion([FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +#pragma mark - IID version compatibility + ++ (void)assertCompatibleIIDVersion { + // We use this flag to disable IID compatibility exception for unit tests. +#ifdef FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION + return; +#else + if (![self isIIDVersionCompatible]) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"FirebaseInstallations will not work correctly with current version of " + @"Firebase Instance ID. Please update your Firebase Instance ID version."]; + } +#endif +} + ++ (BOOL)isIIDVersionCompatible { + Class IIDClass = NSClassFromString(@"FIRInstanceID"); + if (IIDClass == nil) { + // It is OK if there is no IID at all. + return YES; + } + // We expect a compatible version having the method `+[FIRInstanceID usesFIS]` defined. + BOOL isCompatibleVersion = [IIDClass respondsToSelector:NSSelectorFromString(@"usesFIS")]; + return isCompatibleVersion; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m new file mode 100644 index 00000000..92e5fab1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAuthTokenResultInternal.h" + +@implementation FIRInstallationsAuthTokenResult + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationDate { + self = [super init]; + if (self) { + _authToken = [token copy]; + _expirationDate = expirationDate; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h new file mode 100644 index 00000000..0c959dba --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsAuthTokenResult (Internal) + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationTime; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h new file mode 100644 index 00000000..95fdf835 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredItem; +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class represents the required installation ID and auth token data including possible states. + * The data is stored to Keychain via `FIRInstallationsStoredItem` which has only the storage + * relevant data and does not contain any logic. `FIRInstallationsItem` must be used on the logic + * level (not `FIRInstallationsStoredItem`). + */ +@interface FIRInstallationsItem : NSObject + +/// A `FirebaseApp` identifier. +@property(nonatomic, readonly) NSString *appID; +/// A `FirebaseApp` name. +@property(nonatomic, readonly) NSString *firebaseAppName; +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic, assign) FIRInstallationsStatus registrationStatus; + +/// Instance ID default token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName; + +/** + * Populates `FIRInstallationsItem` properties with data from `FIRInstallationsStoredItem`. + * @param item An instance of `FIRInstallationsStoredItem` to get data from. + */ +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item; + +/** + * Creates a stored item with data from the object. + * @return Returns a `FIRInstallationsStoredItem` instance with the data from the object. + */ +- (FIRInstallationsStoredItem *)storedItem; + +/** + * The installation identifier. + * @return Returns a string uniquely identifying the installation. + */ +- (NSString *)identifier; + +/** + * The installation identifier. + * @param appID A `FirebaseApp` identifier. + * @param appName A `FirebaseApp` name. + * @return Returns a string uniquely identifying the installation. + */ ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName; + +/** + * Generate a new Firebase Installation Identifier. + * @return Returns a 22 characters long globally unique string created based on UUID. + */ ++ (NSString *)generateFID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m new file mode 100644 index 00000000..bc819bf8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m @@ -0,0 +1,104 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsStoredItem.h" + +@implementation FIRInstallationsItem + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName { + self = [super init]; + if (self) { + _appID = [appID copy]; + _firebaseAppName = [firebaseAppName copy]; + } + return self; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsItem *clone = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.firebaseAppName]; + clone.firebaseInstallationID = [self.firebaseInstallationID copy]; + clone.refreshToken = [self.refreshToken copy]; + clone.authToken = [self.authToken copy]; + clone.registrationStatus = self.registrationStatus; + + return clone; +} + +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item { + self.firebaseInstallationID = item.firebaseInstallationID; + self.refreshToken = item.refreshToken; + self.authToken = item.authToken; + self.registrationStatus = item.registrationStatus; + self.IIDDefaultToken = item.IIDDefaultToken; +} + +- (FIRInstallationsStoredItem *)storedItem { + FIRInstallationsStoredItem *storedItem = [[FIRInstallationsStoredItem alloc] init]; + storedItem.firebaseInstallationID = self.firebaseInstallationID; + storedItem.refreshToken = self.refreshToken; + storedItem.authToken = self.authToken; + storedItem.registrationStatus = self.registrationStatus; + storedItem.IIDDefaultToken = self.IIDDefaultToken; + return storedItem; +} + +- (nonnull NSString *)identifier { + return [[self class] identifierWithAppID:self.appID appName:self.firebaseAppName]; +} + ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName { + return [appID stringByAppendingString:appName]; +} + ++ (NSString *)generateFID { + NSUUID *UUID = [NSUUID UUID]; + uuid_t UUIDBytes; + [UUID getUUIDBytes:UUIDBytes]; + + NSUInteger UUIDLength = sizeof(uuid_t); + NSData *UUIDData = [NSData dataWithBytes:UUIDBytes length:UUIDLength]; + + uint8_t UUIDLast4Bits = UUIDBytes[UUIDLength - 1] & 0b00001111; + + // FID first 4 bits must be `0111`. The last 4 UUID bits will be cut later to form a proper FID. + // To keep 16 random bytes we copy these last 4 UUID to the FID 1st byte after `0111` prefix. + uint8_t FIDPrefix = 0b01110000 | UUIDLast4Bits; + NSMutableData *FIDData = [NSMutableData dataWithBytes:&FIDPrefix length:1]; + + [FIDData appendData:UUIDData]; + NSString *FIDString = [self base64URLEncodedStringWithData:FIDData]; + + // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5 bytes. + // Our generated ID has 16 bytes UUID + 1 byte prefix which after encoding with base64 will become + // 23 characters plus 1 character for "=" padding. + + // Remove the 23rd character that was added because of the extra 4 bits at the + // end of our 17 byte data and the '=' padding. + return [FIDString substringWithRange:NSMakeRange(0, 22)]; +} + ++ (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + return string; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h new file mode 100644 index 00000000..e4192bf6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +extern FIRLoggerService kFIRLoggerInstallations; + +// FIRInstallationsAPIService.m +extern NSString *const kFIRInstallationsMessageCodeSendAPIRequest; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeParsingAPIResponse; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed; + +// FIRInstallationsIDController.m +extern NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration; + +// FIRInstallationsStoredItem.m +extern NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch; + +// FIRInstallationsStoredAuthToken.m +extern NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch; + +// FIRInstallationsStoredIIDCheckin.m +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch; +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode; + +// FIRInstallations.m +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m new file mode 100644 index 00000000..c2bdf37f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsLogger.h" + +FIRLoggerService kFIRLoggerInstallations = @"[Firebase/Installations]"; + +// FIRInstallationsAPIService.m +NSString *const kFIRInstallationsMessageCodeSendAPIRequest = @"I-FIS001001"; +NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError = @"I-FIS001002"; +NSString *const kFIRInstallationsMessageCodeAPIRequestResponse = @"I-FIS001003"; +NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse = @"I-FIS001004"; +NSString *const kFIRInstallationsMessageCodeParsingAPIResponse = @"I-FIS001005"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed = @"I-FIS001006"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed = @"I-FIS001007"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed = @"I-FIS001008"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed = @"I-FIS001009"; + +// FIRInstallationsIDController.m +NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated = @"I-FIS002000"; +NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated = @"I-FIS002001"; +NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated = @"I-FIS002002"; +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration = @"I-FIS002003"; + +// FIRInstallationsStoredItem.m +NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch = @"I-FIS003000"; + +// FIRInstallationsStoredAuthToken.m +NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch = @"I-FIS004000"; + +// FIRInstallationsStoredIIDCheckin.m +NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch = @"I-FIS007000"; +NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode = @"I-FIS007001"; + +// FIRInstallations.m +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions = @"I-FIS008000"; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m new file mode 100644 index 00000000..a75e3f5b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m @@ -0,0 +1,23 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsVersion.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRInstallationsVersionStr = (const char *const)STR(FIRInstallations_LIB_VERSION); diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h new file mode 100644 index 00000000..e2408caa --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** The class encapsulates a port of a piece FirebaseInstanceID logic required to migrate IID. */ +@interface FIRInstallationsIIDStore : NSObject + +/** + * Retrieves existing IID if present. + * @return Returns a promise that is resolved with IID string if IID has been found or rejected with + * an error otherwise. + */ +- (FBLPromise *)existingIID; + +/** + * Deletes existing IID if present. + * @return Returns a promise that is resolved with `[NSNull null]` if the IID was successfully. + * deleted or was not found. The promise is rejected otherwise. + */ +- (FBLPromise *)deleteExistingIID; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m new file mode 100644 index 00000000..1f3a82af --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m @@ -0,0 +1,236 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import "FIRInstallationsErrorUtil.h" + +static NSString *const kFIRInstallationsIIDKeyPairPublicTagPrefix = + @"com.google.iid.keypair.public-"; +static NSString *const kFIRInstallationsIIDKeyPairPrivateTagPrefix = + @"com.google.iid.keypair.private-"; +static NSString *const kFIRInstallationsIIDCreationTimePlistKey = @"|S|cre"; + +@implementation FIRInstallationsIIDStore + +- (FBLPromise *)existingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + if (![self hasPlistIIDFlag]) { + return nil; + } + + NSData *IIDPublicKeyData = [self IIDPublicKeyData]; + return [self IIDWithPublicKeyData:IIDPublicKeyData]; + }] + .validate(^BOOL(NSString *_Nullable IID) { + return IID.length > 0; + }); +} + +- (FBLPromise *)deleteExistingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + NSError *error; + if (![self deleteIIDFlagFromPlist:&error]) { + return error; + } + + if (![self deleteIID:&error]) { + return error; + } + + return [NSNull null]; + }]; +} + +#pragma mark - IID decoding + +- (NSString *)IIDWithPublicKeyData:(NSData *)publicKeyData { + NSData *publicKeySHA1 = [self sha1WithData:publicKeyData]; + + const uint8_t *bytes = publicKeySHA1.bytes; + NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1]; + + uint8_t b0 = bytes[0]; + // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0 + // and then adding 0x70 to it. + b0 = 0x70 + (0xF & b0); + // failsafe should give you back b0 itself + b0 = (b0 & 0xFF); + [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0]; + NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))]; + return [self base64URLEncodedStringWithData:data]; +} + +- (NSData *)sha1WithData:(NSData *)data { + unsigned char output[CC_SHA1_DIGEST_LENGTH]; + unsigned int length = (unsigned int)[data length]; + + CC_SHA1(data.bytes, length, output); + return [NSData dataWithBytes:output length:CC_SHA1_DIGEST_LENGTH]; +} + +- (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + string = [string stringByReplacingOccurrencesOfString:@"=" withString:@""]; + return string; +} + +#pragma mark - Keychain + +- (NSData *)IIDPublicKeyData { + NSString *tag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *query = [self keyPairQueryWithTag:tag returnData:YES]; + + CFTypeRef keyRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + return nil; + } + + return (__bridge NSData *)keyRef; +} + +- (BOOL)deleteIID:(NSError **)outError { + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix + error:outError]) { + return NO; + } + + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPrivateTagPrefix + error:outError]) { + return NO; + } + + return YES; +} + +- (BOOL)deleteKeychainKeyWithTagPrefix:(NSString *)tagPrefix error:(NSError **)outError { + NSString *keyTag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *keyQuery = [self keyPairQueryWithTag:keyTag returnData:NO]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keyQuery); + + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete" status:status], + outError); + return NO; + } + + return YES; +} + +- (NSDictionary *)keyPairQueryWithTag:(NSString *)tag returnData:(BOOL)shouldReturnData { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + query[(__bridge id)kSecClass] = (__bridge id)kSecClassKey; + query[(__bridge id)kSecAttrApplicationTag] = tagData; + query[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA; + if (shouldReturnData) { + query[(__bridge id)kSecReturnData] = @(YES); + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +- (NSString *)keychainKeyTagWithPrefix:(NSString *)prefix { + NSString *mainAppBundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (mainAppBundleID.length == 0) { + return nil; + } + return [NSString stringWithFormat:@"%@%@", prefix, mainAppBundleID]; +} + +- (NSString *)mainbundleIdentifier { + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleIdentifier.length) { + return nil; + } + return bundleIdentifier; +} + +#pragma mark - Plist + +- (BOOL)deleteIIDFlagFromPlist:(NSError **)outError { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return YES; + } + + NSMutableDictionary *plistContent = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; + plistContent[kFIRInstallationsIIDCreationTimePlistKey] = nil; + + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + return [plistContent writeToURL:[NSURL fileURLWithPath:path] error:outError]; + } + + return [plistContent writeToFile:path atomically:YES]; +} + +- (BOOL)hasPlistIIDFlag { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return NO; + } + + NSDictionary *plistContent = [[NSDictionary alloc] initWithContentsOfFile:path]; + return plistContent[kFIRInstallationsIIDCreationTimePlistKey] != nil; +} + +- (NSString *)plistPath { + NSString *plistNameWithExtension = @"com.google.iid-keypair.plist"; + NSString *_subDirectoryName = @"Google/FirebaseInstanceID"; + + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h new file mode 100644 index 00000000..ed98e3d7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class reads a default IID token from IID store if available. + */ +@interface FIRInstallationsIIDTokenStore : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID; + +- (FBLPromise *)existingIIDDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m new file mode 100644 index 00000000..b2b69313 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m @@ -0,0 +1,158 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDTokenStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import + +#import "FIRInstallationsErrorUtil.h" + +static NSString *const kFIRInstallationsIIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstallationsIIDTokenInfo : NSObject +@property(nonatomic, nullable, copy) NSString *token; +@end + +@implementation FIRInstallationsIIDTokenInfo + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)coder { +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { + self = [super init]; + if (self) { + _token = [coder decodeObjectOfClass:[NSString class] forKey:@"token"]; + } + return self; +} + +@end + +@interface FIRInstallationsIIDTokenStore () +@property(nonatomic, readonly) NSString *GCMSenderID; +@end + +@implementation FIRInstallationsIIDTokenStore + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + _GCMSenderID = GCMSenderID; + } + return self; +} + +- (FBLPromise *)existingIIDDefaultToken { + return [[FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + return [self IIDDefaultTokenData]; + }] onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + then:^id _Nullable(NSData *_Nullable keychainData) { + return [self IIDCheckinWithData:keychainData]; + }]; +} + +- (FBLPromise *)IIDCheckinWithData:(NSData *)data { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSError *archiverError; + NSKeyedUnarchiver *unarchiver; + if (@available(iOS 11.0, tvOS 11.0, macOS 10.13, *)) { + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&archiverError]; + } else { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + archiverError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + + if (!unarchiver) { + NSError *error = archiverError ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:error]; + return resultPromise; + } + + [unarchiver setClass:[FIRInstallationsIIDTokenInfo class] forClassName:@"FIRInstanceIDTokenInfo"]; + FIRInstallationsIIDTokenInfo *IIDTokenInfo = + [unarchiver decodeObjectOfClass:[FIRInstallationsIIDTokenInfo class] + forKey:NSKeyedArchiveRootObjectKey]; + + if (IIDTokenInfo.token.length < 1) { + [resultPromise reject:[FIRInstallationsErrorUtil corruptedIIDTokenData]]; + return resultPromise; + } + + [resultPromise fulfill:IIDTokenInfo.token]; + + return resultPromise; +} + +- (FBLPromise *)IIDDefaultTokenData { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSMutableDictionary *keychainQuery = [self IIDDefaultTokenDataKeychainQuery]; + NSError *error; + NSData *data = [GULKeychainUtils getItemWithQuery:keychainQuery error:&error]; + + if (data) { + [resultPromise fulfill:data]; + return resultPromise; + } else { + NSError *outError = error ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:outError]; + return resultPromise; + } +} + +- (NSMutableDictionary *)IIDDefaultTokenDataKeychainQuery { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + finalQuery[(__bridge NSString *)kSecAttrGeneric] = kFIRInstallationsIIDTokenKeychainId; + + NSString *account = [self IIDAppIdentifier]; + if ([account length]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + + finalQuery[(__bridge NSString *)kSecAttrService] = + [self serviceKeyForAuthorizedEntity:self.GCMSenderID scope:@"*"]; + return finalQuery; +} + +- (NSString *)IIDAppIdentifier { + return [[NSBundle mainBundle] bundleIdentifier] ?: @""; +} + +- (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h new file mode 100644 index 00000000..b45475d1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstallationsUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstallationsHeartbeatKey; + +/** + * The class is responsible for interacting with HTTP REST API for Installations. + */ +@interface FIRInstallationsAPIService : NSObject + +/** + * The default initializer. + * @param APIKey The Firebase project API key (see `FIROptions.APIKey`). + * @param projectID The Firebase project ID (see `FIROptions.projectID`). + */ +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID; + +/** + * Sends a request to register a new FID to get auth and refresh tokens. + * @param installation The `FIRInstallationsItem` instance with the FID to register. + * @return A promise that is resolved with a new `FIRInstallationsItem` instance with valid tokens. + * It is rejected with an error in case of a failure. + */ +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation; + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation; + +/** + * Sends a request to delete the installation, related auth tokens and all related data from the + * server. + * @param installation The installation to delete. + * @return Returns a promise that is resolved with the passed installation on successful deletion or + * is rejected with an error otherwise. + */ +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m new file mode 100644 index 00000000..70218476 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m @@ -0,0 +1,361 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAPIService.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem+RegisterInstallationAPI.h" +#import "FIRInstallationsLogger.h" +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +NSString *const kFIRInstallationsAPIBaseURL = @"https://firebaseinstallations.googleapis.com"; +NSString *const kFIRInstallationsAPIKey = @"X-Goog-Api-Key"; +NSString *const kFIRInstallationsBundleId = @"X-Ios-Bundle-Identifier"; +NSString *const kFIRInstallationsIIDMigrationAuthHeader = @"x-goog-fis-ios-iid-migration-auth"; +NSString *const kFIRInstallationsHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstallationsHeartbeatTag = @"fire-installations"; +NSString *const kFIRInstallationsUserAgentKey = @"X-firebase-client"; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsURLSessionResponse : NSObject +@property(nonatomic) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic) NSData *data; + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data; +@end + +@implementation FIRInstallationsURLSessionResponse + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data { + self = [super init]; + if (self) { + _HTTPResponse = response; + _data = data ?: [NSData data]; + } + return self; +} + +@end + +@interface FIRInstallationsAPIService () +@property(nonatomic, readonly) NSURLSession *URLSession; +@property(nonatomic, readonly) NSString *APIKey; +@property(nonatomic, readonly) NSString *projectID; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstallationsAPIService + +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID { + NSURLSession *URLSession = [NSURLSession + sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + return [self initWithURLSession:URLSession APIKey:APIKey projectID:projectID]; +} + +/// The initializer for tests. +- (instancetype)initWithURLSession:(NSURLSession *)URLSession + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID { + self = [super init]; + if (self) { + _URLSession = URLSession; + _APIKey = [APIKey copy]; + _projectID = [projectID copy]; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation { + return [self registerRequestWithInstallation:installation] + .then(^id _Nullable(NSURLRequest *_Nullable request) { + return [self sendURLRequest:request]; + }) + .then(^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self registeredInstallationWithInstallation:installation serverResponse:response]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + return [self authTokenRequestWithInstallation:installation] + .then(^id _Nullable(NSURLRequest *_Nullable request) { + return [self sendURLRequest:request]; + }) + .then(^FBLPromise *( + FIRInstallationsURLSessionResponse *response) { + return [self authTokenWithServerResponse:response]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsStoredAuthToken *authToken) { + FIRInstallationsItem *updatedInstallation = [installation copy]; + updatedInstallation.authToken = authToken; + return updatedInstallation; + }); +} + +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation { + return [self deleteInstallationRequestWithInstallation:installation] + .then(^id _Nullable(NSURLRequest *_Nullable request) { + return [self sendURLRequest:request]; + }) + .then(^id _Nullable(FIRInstallationsURLSessionResponse *_Nullable value) { + // Return the original installation on success. + return installation; + }); +} + +#pragma mark - Register Installation + +- (FBLPromise *)registerRequestWithInstallation: + (FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/", + kFIRInstallationsAPIBaseURL, self.projectID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{ + @"fid" : installation.firebaseInstallationID, + @"authVersion" : @"FIS_v2", + @"appId" : installation.appID, + @"sdkVersion" : [self SDKVersion] + }; + + NSDictionary *headers; + if (installation.IIDDefaultToken) { + headers = @{kFIRInstallationsIIDMigrationAuthHeader : installation.IIDDefaultToken}; + } + + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:nil + additionalHeaders:headers]; +} + +- (FBLPromise *) + registeredInstallationWithInstallation:(FIRInstallationsItem *)installation + serverResponse:(FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsItem *registeredInstallation = + [installation registeredInstallationWithJSONData:response.data + date:[NSDate date] + error:&error]; + if (registeredInstallation == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed, + @"Failed to parse FIRInstallationsItem: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed, + @"FIRInstallationsItem parsed successfully."); + return registeredInstallation; + }]; +} + +#pragma mark - Auth token + +- (FBLPromise *)authTokenRequestWithInstallation: + (FIRInstallationsItem *)installation { + NSString *URLString = + [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/authTokens:generate", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{@"installation" : @{@"sdkVersion" : [self SDKVersion]}}; + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:installation.refreshToken]; +} + +- (FBLPromise *)authTokenWithServerResponse: + (FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsStoredAuthToken *token = + [FIRInstallationsItem authTokenWithGenerateTokenAPIJSONData:response.data + date:[NSDate date] + error:&error]; + if (token == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed, + @"Failed to parse FIRInstallationsStoredAuthToken: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed, + @"FIRInstallationsStoredAuthToken parsed successfully."); + return token; + }]; +} + +#pragma mark - Delete Installation + +- (FBLPromise *)deleteInstallationRequestWithInstallation: + (FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + return [self requestWithURL:URL + HTTPMethod:@"DELETE" + bodyDict:@{} + refreshToken:installation.refreshToken]; +} + +#pragma mark - URL Request +- (FBLPromise *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken { + return [self requestWithURL:requestURL + HTTPMethod:HTTPMethod + bodyDict:bodyDict + refreshToken:refreshToken + additionalHeaders:nil]; +} + +- (FBLPromise *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken + additionalHeaders:(nullable NSDictionary *) + additionalHeaders { + return [FBLPromise + onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + __block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL]; + request.HTTPMethod = HTTPMethod; + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + [request addValue:self.APIKey forHTTPHeaderField:kFIRInstallationsAPIKey]; + [request addValue:bundleIdentifier forHTTPHeaderField:kFIRInstallationsBundleId]; + [self setJSONHTTPBody:bodyDict forRequest:request]; + if (refreshToken) { + NSString *authHeader = [NSString stringWithFormat:@"FIS_v2 %@", refreshToken]; + [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; + } + // User agent Header. + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstallationsUserAgentKey]; + // Heartbeat Header. + [request setValue:@([FIRHeartbeatInfo + heartbeatCodeForTag:kFIRInstallationsHeartbeatTag]) + .stringValue + forHTTPHeaderField:kFIRInstallationsHeartbeatKey]; + [additionalHeaders + enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, NSString *_Nonnull obj, + BOOL *_Nonnull stop) { + [request setValue:obj forHTTPHeaderField:key]; + }]; + + return [request copy]; + }]; +} + +- (FBLPromise *)URLRequestPromise:(NSURLRequest *)request { + return [[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeSendAPIRequest, + @"Sending request: %@, body:%@, headers: %@.", request, + [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding], + request.allHTTPHeaderFields); + [[self.URLSession + dataTaskWithRequest:request + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIRequestNetworkError, + @"Request failed: %@, error: %@.", request, error); + reject(error); + } else { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeAPIRequestResponse, + @"Request response received: %@, error: %@, body: %@.", request, error, + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + fulfill([[FIRInstallationsURLSessionResponse alloc] + initWithResponse:(NSHTTPURLResponse *)response + data:data]); + } + }] resume]; + }] then:^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self validateHTTPResponseStatusCode:response]; + }]; +} + +- (FBLPromise *)validateHTTPResponseStatusCode: + (FIRInstallationsURLSessionResponse *)response { + NSInteger statusCode = response.HTTPResponse.statusCode; + return [FBLPromise do:^id _Nullable { + if (statusCode < 200 || statusCode >= 300) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse, + @"Unexpected API response: %@, body: %@.", response.HTTPResponse, + [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]); + return [FIRInstallationsErrorUtil APIErrorWithHTTPResponse:response.HTTPResponse + data:response.data]; + } + return response; + }]; +} + +- (FBLPromise *)sendURLRequest:(NSURLRequest *)request { + return [FBLPromise attempts:1 + delay:1 + condition:^BOOL(NSInteger remainingAttempts, NSError *_Nonnull error) { + return [FIRInstallationsErrorUtil isAPIError:error withHTTPCode:500]; + } + retry:^id _Nullable { + return [self URLRequestPromise:request]; + }]; +} + +- (NSString *)SDKVersion { + return [NSString stringWithFormat:@"i:%s", FIRInstallationsVersionStr]; +} + +#pragma mark - JSON + +- (void)setJSONHTTPBody:(NSDictionary *)body + forRequest:(NSMutableURLRequest *)request { + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + + NSError *error; + NSData *JSONData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error]; + if (JSONData == nil) { + // TODO: Log or return an error. + } + request.HTTPBody = JSONData; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h new file mode 100644 index 00000000..cc6b5432 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +@class FIRInstallationsStoredAuthToken; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsItem (RegisterInstallationAPI) + +/** + * Parses and validates the Register Installation API response and returns a corresponding + * `FIRInstallationsItem` instance on success. + * @param JSONData The data with JSON encoded API response. + * @param date The Auth Token expiration date will be calculated as `date` + + * `response.authToken.expiresIn`. For most of the cases `[NSDate date]` should be passed there. A + * different value may be passed e.g. for unit tests. + * @param outError A pointer to assign a specific `NSError` instance in case of failure. No error is + * assigned in case of success. + * @return Returns a new `FIRInstallationsItem` instance in the success case or `nil` otherwise. + */ +- (nullable FIRInstallationsItem *)registeredInstallationWithJSONData:(NSData *)JSONData + date:(NSDate *)date + error: + (NSError *_Nullable *)outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m new file mode 100644 index 00000000..569e35b9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m @@ -0,0 +1,142 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem+RegisterInstallationAPI.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsStoredAuthToken.h" + +@implementation FIRInstallationsItem (RegisterInstallationAPI) + +- (nullable FIRInstallationsItem *) + registeredInstallationWithJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError *__autoreleasing _Nullable *_Nullable)outError { + NSDictionary *responseJSON = [FIRInstallationsItem dictionaryFromJSONData:data error:outError]; + if (!responseJSON) { + return nil; + } + + NSString *refreshToken = [FIRInstallationsItem validStringOrNilForKey:@"refreshToken" + fromDict:responseJSON]; + if (refreshToken == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"refreshToken"], + outError); + return nil; + } + + NSDictionary *authTokenDict = responseJSON[@"authToken"]; + if (![authTokenDict isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken"], + outError); + return nil; + } + + FIRInstallationsStoredAuthToken *authToken = + [FIRInstallationsItem authTokenWithJSONDict:authTokenDict date:date error:outError]; + if (authToken == nil) { + return nil; + } + + FIRInstallationsItem *installation = + [[FIRInstallationsItem alloc] initWithAppID:self.appID firebaseAppName:self.firebaseAppName]; + NSString *installationID = [FIRInstallationsItem validStringOrNilForKey:@"fid" + fromDict:responseJSON]; + installation.firebaseInstallationID = installationID ?: self.firebaseInstallationID; + installation.refreshToken = refreshToken; + installation.authToken = authToken; + installation.registrationStatus = FIRInstallationStatusRegistered; + + return installation; +} + +#pragma mark - Auth token + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError { + NSDictionary *dict = [self dictionaryFromJSONData:data error:outError]; + if (!dict) { + return nil; + } + + return [self authTokenWithJSONDict:dict date:date error:outError]; +} + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError { + NSString *token = [self validStringOrNilForKey:@"token" fromDict:dict]; + if (token == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken.token"], + outError); + return nil; + } + + NSString *expiresInString = [self validStringOrNilForKey:@"expiresIn" fromDict:dict]; + if (expiresInString == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil + FIDRegistrationErrorWithResponseMissingField:@"authToken.expiresIn"], + outError); + return nil; + } + + // The response should contain the string in format like "604800s". + // The server should never response with anything else except seconds. + // Just drop the last character and parse a number from string. + NSString *expiresInSeconds = [expiresInString substringToIndex:expiresInString.length - 1]; + NSTimeInterval expiresIn = [expiresInSeconds doubleValue]; + NSDate *expirationDate = [date dateByAddingTimeInterval:expiresIn]; + + FIRInstallationsStoredAuthToken *authToken = [[FIRInstallationsStoredAuthToken alloc] init]; + authToken.status = FIRInstallationsAuthTokenStatusTokenReceived; + authToken.token = token; + authToken.expirationDate = expirationDate; + + return authToken; +} + +#pragma mark - JSON + ++ (nullable NSDictionary *)dictionaryFromJSONData:(NSData *)data + error:(NSError **)outError { + NSError *error; + NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + + if (![responseJSON isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer([FIRInstallationsErrorUtil JSONSerializationError:error], + outError); + return nil; + } + + return responseJSON; +} + ++ (NSString *)validStringOrNilForKey:(NSString *)key fromDict:(NSDictionary *)dict { + NSString *string = dict[key]; + if ([string isKindOfClass:[NSString class]] && string.length > 0) { + return string; + } + return nil; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h new file mode 100644 index 00000000..ab2092d2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBLPromise; +@class FIRInstallationsItem; + +/** + * The class is responsible for managing FID for a given `FIRApp`. + */ +@interface FIRInstallationsIDController : NSObject + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(nullable NSString *)accessGroup; + +- (FBLPromise *)getInstallationItem; + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh; + +- (FBLPromise *)deleteInstallation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m new file mode 100644 index 00000000..325b5bfd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m @@ -0,0 +1,480 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIDController.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "FIRInstallationsAPIService.h" +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIIDStore.h" +#import "FIRInstallationsIIDTokenStore.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsSingleOperationPromiseCache.h" +#import "FIRInstallationsStore.h" + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsStoredAuthToken.h" + +const NSNotificationName FIRInstallationIDDidChangeNotification = + @"FIRInstallationIDDidChangeNotification"; +NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey = + @"FIRInstallationIDDidChangeNotification"; + +NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 hour. + +static NSString *const kKeychainService = @"com.firebase.FIRInstallations.installations"; + +@interface FIRInstallationsIDController () +@property(nonatomic, readonly) NSString *appID; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsStore *installationsStore; +@property(nonatomic, readonly) FIRInstallationsIIDStore *IIDStore; +@property(nonatomic, readonly) FIRInstallationsIIDTokenStore *IIDTokenStore; + +@property(nonatomic, readonly) FIRInstallationsAPIService *APIService; + +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *getInstallationPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *authTokenPromiseCache; +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *authTokenForcingRefreshPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *deleteInstallationPromiseCache; +@end + +@implementation FIRInstallationsIDController + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(nullable NSString *)accessGroup { + NSString *serviceName = [FIRInstallationsIDController keychainServiceWithAppID:appID]; + GULKeychainStorage *secureStorage = [[GULKeychainStorage alloc] initWithService:serviceName]; + FIRInstallationsStore *installationsStore = + [[FIRInstallationsStore alloc] initWithSecureStorage:secureStorage accessGroup:accessGroup]; + + // Use `GCMSenderID` as project identifier when `projectID` is not available. + NSString *APIServiceProjectID = (projectID.length > 0) ? projectID : GCMSenderID; + FIRInstallationsAPIService *apiService = + [[FIRInstallationsAPIService alloc] initWithAPIKey:APIKey projectID:APIServiceProjectID]; + + FIRInstallationsIIDStore *IIDStore = [[FIRInstallationsIIDStore alloc] init]; + FIRInstallationsIIDTokenStore *IIDCheckingStore = + [[FIRInstallationsIIDTokenStore alloc] initWithGCMSenderID:GCMSenderID]; + + return [self initWithGoogleAppID:appID + appName:appName + installationsStore:installationsStore + APIService:apiService + IIDStore:IIDStore + IIDTokenStore:IIDCheckingStore]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + installationsStore:(FIRInstallationsStore *)installationsStore + APIService:(FIRInstallationsAPIService *)APIService + IIDStore:(FIRInstallationsIIDStore *)IIDStore + IIDTokenStore:(FIRInstallationsIIDTokenStore *)IIDTokenStore { + self = [super init]; + if (self) { + _appID = appID; + _appName = appName; + _installationsStore = installationsStore; + _APIService = APIService; + _IIDStore = IIDStore; + _IIDTokenStore = IIDTokenStore; + + __weak FIRInstallationsIDController *weakSelf = self; + + _getInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createGetInstallationItemPromise]; + }]; + + _authTokenPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:NO]; + }]; + + _authTokenForcingRefreshPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:YES]; + }]; + + _deleteInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createDeleteInstallationPromise]; + }]; + } + return self; +} + +#pragma mark - Get Installation. + +- (FBLPromise *)getInstallationItem { + return [self.getInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createGetInstallationItemPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewGetInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + FBLPromise *installationItemPromise = + [self getStoredInstallation].recover(^id(NSError *error) { + return [self createAndSaveFID]; + }); + + // Initiate registration process on success if needed, but return the installation without waiting + // for it. + installationItemPromise.then(^id(FIRInstallationsItem *installation) { + [self getAuthTokenForcingRefresh:NO]; + return nil; + }); + + return installationItemPromise; +} + +- (FBLPromise *)getStoredInstallation { + return [self.installationsStore installationForAppID:self.appID appName:self.appName].validate( + ^BOOL(FIRInstallationsItem *installation) { + BOOL isValid = NO; + switch (installation.registrationStatus) { + case FIRInstallationStatusUnregistered: + case FIRInstallationStatusRegistered: + isValid = YES; + break; + + case FIRInstallationStatusUnknown: + isValid = NO; + break; + } + + return isValid; + }); +} + +- (FBLPromise *)createAndSaveFID { + return [self migrateOrGenerateInstallation] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self saveInstallation:installation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *installation) { + [self postFIDDidChangeNotification]; + return installation; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installation { + return [self.installationsStore saveInstallation:installation].then( + ^FIRInstallationsItem *(NSNull *result) { + return installation; + }); +} + +/** + * Tries to migrate IID data stored by FirebaseInstanceID SDK or generates a new Installation ID if + * not found. + */ +- (FBLPromise *)migrateOrGenerateInstallation { + if (![self isDefaultApp]) { + // Existing IID should be used only for default FirebaseApp. + FIRInstallationsItem *installation = + [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + return [FBLPromise resolvedWith:installation]; + } + + return [[[FBLPromise + all:@[ [self.IIDStore existingIID], [self.IIDTokenStore existingIIDDefaultToken] ]] + then:^id _Nullable(NSArray *_Nullable results) { + NSString *existingIID = results[0]; + NSString *IIDDefaultToken = results[1]; + + return [self createInstallationWithFID:existingIID IIDDefaultToken:IIDDefaultToken]; + }] recover:^id _Nullable(NSError *_Nonnull error) { + return [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + }]; +} + +- (FIRInstallationsItem *)createInstallationWithFID:(NSString *)FID + IIDDefaultToken:(nullable NSString *)IIDDefaultToken { + FIRInstallationsItem *installation = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.appName]; + installation.firebaseInstallationID = FID; + installation.IIDDefaultToken = IIDDefaultToken; + installation.registrationStatus = FIRInstallationStatusUnregistered; + return installation; +} + +#pragma mark - FID registration + +- (FBLPromise *)registerInstallationIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusRegistered: + // Already registered. Do nothing. + return [FBLPromise resolvedWith:installation]; + + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // Registration required. Proceed. + break; + } + + return [self.APIService registerInstallation:installation] + .catch(^(NSError *_Nonnull error) { + if ([self doesRegistrationErrorRequireConfigChange:error]) { + FIRLogError(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInvalidFirebaseConfiguration, + @"Firebase Installation registration failed for app with name: %@, error:\n" + @"%@\nPlease make sure you use valid GoogleService-Info.plist", + self.appName, error.userInfo[NSLocalizedFailureReasonErrorKey]); + } + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + return [self saveInstallation:registeredInstallation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *registeredInstallation) { + // Server may respond with a different FID if the sent one cannot be accepted. + if (![registeredInstallation.firebaseInstallationID + isEqualToString:installation.firebaseInstallationID]) { + [self postFIDDidChangeNotification]; + } + return registeredInstallation; + }); +} + +- (BOOL)doesRegistrationErrorRequireConfigChange:(NSError *)error { + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + if (![HTTPError isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + switch (HTTPError.HTTPResponse.statusCode) { + // These are the errors that require Firebase configuration change. + case FIRInstallationsRegistrationHTTPCodeInvalidArgument: + case FIRInstallationsRegistrationHTTPCodeInvalidAPIKey: + case FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch: + case FIRInstallationsRegistrationHTTPCodeProjectNotFound: + return YES; + + default: + return NO; + } +} + +#pragma mark - Auth Token + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh { + if (forceRefresh || [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] != nil) { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingOrCreateNewPromise]; + } else { + return [self.authTokenPromiseCache getExistingPendingOrCreateNewPromise]; + } +} + +- (FBLPromise *)installationWithValidAuthTokenForcingRefresh: + (BOOL)forceRefresh { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated, + @"-[FIRInstallationsIDController installationWithValidAuthTokenForcingRefresh:%@], " + @"appName: %@", + @(forceRefresh), self.appName); + + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self registerInstallationIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + BOOL isTokenExpiredOrExpiresSoon = + [registeredInstallation.authToken.expirationDate timeIntervalSinceDate:[NSDate date]] < + kFIRInstallationsTokenExpirationThreshold; + if (forceRefresh || isTokenExpiredOrExpiresSoon) { + return [self refreshAuthTokenForInstallation:registeredInstallation]; + } else { + return registeredInstallation; + } + }) + .recover(^id(NSError *error) { + return [self regenerateFIDOnRefreshTokenErrorIfNeeded:error]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + return [[self.APIService refreshAuthTokenForInstallation:installation] + then:^id _Nullable(FIRInstallationsItem *_Nullable refreshedInstallation) { + return [self saveInstallation:refreshedInstallation]; + }]; +} + +- (id)regenerateFIDOnRefreshTokenErrorIfNeeded:(NSError *)error { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + // No recovery possible. Return the same error. + return error; + } + + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + switch (HTTPError.HTTPResponse.statusCode) { + case FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication: + case FIRInstallationsAuthTokenHTTPCodeFIDNotFound: + // The stored installation was damaged or blocked by the server. + // Delete the stored installation then generate and register a new one. + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self deleteInstallationLocally:installation]; + }) + .then(^FBLPromise *(id result) { + return [self installationWithValidAuthTokenForcingRefresh:NO]; + }); + + default: + // No recovery possible. Return the same error. + return error; + } +} + +#pragma mark - Delete FID + +- (FBLPromise *)deleteInstallation { + return [self.deleteInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createDeleteInstallationPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + // Check for ongoing requests first, if there is no a request, then check local storage for + // existing installation. + FBLPromise *currentInstallationPromise = + [self mostRecentInstallationOperation] ?: [self getStoredInstallation]; + + return currentInstallationPromise + .then(^id(FIRInstallationsItem *installation) { + return [self sendDeleteInstallationRequestIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *installation) { + // Remove the installation from the local storage. + return [self deleteInstallationLocally:installation]; + }); +} + +- (FBLPromise *)deleteInstallationLocally:(FIRInstallationsItem *)installation { + return [self.installationsStore removeInstallationForAppID:installation.appID + appName:installation.firebaseAppName] + .then(^FBLPromise *(NSNull *result) { + return [self deleteExistingIIDIfNeeded]; + }) + .then(^NSNull *(NSNull *result) { + [self postFIDDidChangeNotification]; + return result; + }); +} + +- (FBLPromise *)sendDeleteInstallationRequestIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // The installation is not registered, so it is safe to be deleted as is, so return early. + return [FBLPromise resolvedWith:installation]; + break; + + case FIRInstallationStatusRegistered: + // Proceed to de-register the installation on the server. + break; + } + + return [self.APIService deleteInstallation:installation].recover(^id(NSError *APIError) { + if ([FIRInstallationsErrorUtil isAPIError:APIError withHTTPCode:404]) { + // The installation was not found on the server. + // Return success. + return installation; + } else { + // Re-throw the error otherwise. + return APIError; + } + }); +} + +- (FBLPromise *)deleteExistingIIDIfNeeded { + if ([self isDefaultApp]) { + return [self.IIDStore deleteExistingIID]; + } else { + return [FBLPromise resolvedWith:[NSNull null]]; + } +} + +- (nullable FBLPromise *)mostRecentInstallationOperation { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] + ?: [self.authTokenPromiseCache getExistingPendingPromise] + ?: [self.getInstallationPromiseCache getExistingPendingPromise]; +} + +#pragma mark - Notifications + +- (void)postFIDDidChangeNotification { + [[NSNotificationCenter defaultCenter] + postNotificationName:FIRInstallationIDDidChangeNotification + object:nil + userInfo:@{kFIRInstallationIDDidChangeNotificationAppNameKey : self.appName}]; +} + +#pragma mark - Default App + +- (BOOL)isDefaultApp { + return [self.appName isEqualToString:kFIRDefaultAppName]; +} + +#pragma mark - Keychain + ++ (NSString *)keychainServiceWithAppID:(NSString *)appID { +#if TARGET_OS_MACCATALYST || TARGET_OS_OSX + // We need to keep service name unique per application on macOS. + // Applications on macOS may request access to Keychain items stored by other applications. It + // means that when the app looks up for a relevant Keychain item in the service scope it will + // request user password to grant access to the Keychain if there are other Keychain items from + // other applications stored under the same Keychain Service. + return [kKeychainService stringByAppendingFormat:@".%@", appID]; +#else + // Use a constant Keychain service for non-macOS because: + // 1. Keychain items cannot be shared between apps until configured specifically so the service + // name collisions are not a concern + // 2. We don't want to change the service name to avoid doing a migration. + return kKeychainService; +#endif +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h new file mode 100644 index 00000000..aeb54e50 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class makes sure the a single operation (represented by a promise) is performed at a time. If + * there is an ongoing operation, then its existing corresponding promise will be returned instead + * of starting a new operation. + */ +@interface FIRInstallationsSingleOperationPromiseCache<__covariant ResultType> : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The designated initializer. + * @param newOperationHandler The block that must return a new promise representing the + * single-at-a-time operation. The promise should be fulfilled when the operation is completed. The + * factory block will be used to create a new promise when needed. + */ +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler NS_DESIGNATED_INITIALIZER; + +/** + * Creates a new promise or returns an existing pending one. + * @return Returns and existing pending promise if exists. If the pending promise does not exist + * then a new one will be created using the `factory` block passed in the initializer. Once the + * pending promise gets resolved, it is removed, so calling the method again will lead to creating + * and caching another promise. + */ +- (FBLPromise *)getExistingPendingOrCreateNewPromise; + +/** + * Returns an existing pending promise or `nil`. + * @return Returns an existing pending promise if there is one or `nil` otherwise. + */ +- (nullable FBLPromise *)getExistingPendingPromise; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m new file mode 100644 index 00000000..dfccfe36 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsSingleOperationPromiseCache.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +@interface FIRInstallationsSingleOperationPromiseCache () +@property(nonatomic, readonly) FBLPromise *_Nonnull (^newOperationHandler)(void); +@property(nonatomic, nullable) FBLPromise *pendingPromise; +@end + +@implementation FIRInstallationsSingleOperationPromiseCache + +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler { + if (newOperationHandler == nil) { + [NSException raise:NSInvalidArgumentException + format:@"`newOperationHandler` must not be `nil`."]; + } + + self = [super init]; + if (self) { + _newOperationHandler = [newOperationHandler copy]; + } + return self; +} + +- (FBLPromise *)getExistingPendingOrCreateNewPromise { + @synchronized(self) { + if (!self.pendingPromise) { + self.pendingPromise = self.newOperationHandler(); + + self.pendingPromise + .then(^id(id result) { + @synchronized(self) { + self.pendingPromise = nil; + return nil; + } + }) + .catch(^void(NSError *error) { + @synchronized(self) { + self.pendingPromise = nil; + } + }); + } + + return self.pendingPromise; + } +} + +- (nullable FBLPromise *)getExistingPendingPromise { + @synchronized(self) { + return self.pendingPromise; + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h new file mode 100644 index 00000000..3edc6920 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The enum represent possible states of the installation ID. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredItem`. Modification + * of it can lead to incompatibility with previous version. Any modification must be evaluated and, + * if it is really needed, the `storageVersion` must be bumped and proper migration code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsStatus) { + /** Represents either an initial status when a FIRInstallationsItem instance was created but not + * stored to Keychain or an undefined status (e.g. when the status failed to deserialize). + */ + FIRInstallationStatusUnknown, + /// The Firebase Installation has not yet been registered with FIS. + FIRInstallationStatusUnregistered, + /// The Firebase Installation has successfully been registered with FIS. + FIRInstallationStatusRegistered, +}; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h new file mode 100644 index 00000000..b86fb39a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; +@class GULKeychainStorage; + +NS_ASSUME_NONNULL_BEGIN + +/// The user defaults suite name used to store data. +extern NSString *const kFIRInstallationsStoreUserDefaultsID; + +/// The class is responsible for storing and accessing the installations data. +@interface FIRInstallationsStore : NSObject + +/** + * The default initializer. + * @param storage The secure storage to save installations data. + * @param accessGroup The Keychain Access Group to store and request the installations data. + */ +- (instancetype)initWithSecureStorage:(GULKeychainStorage *)storage + accessGroup:(nullable NSString *)accessGroup; + +/** + * Retrieves existing installation ID if there is. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a `FBLPromise` instance. The promise is resolved with a FIRInstallationsItem + * instance if there is a valid installation stored for `appID` and `appName`. The promise is + * rejected with a specific error when the installation has not been found or with another possible + * error. + */ +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName; + +/** + * Saves the given installation. + * + * @param installationItem The installation data. + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem; + +/** + * Removes installation data for the given app parameters. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m new file mode 100644 index 00000000..46f58dba --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m @@ -0,0 +1,126 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStore.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsStoredItem.h" + +NSString *const kFIRInstallationsStoreUserDefaultsID = @"com.firebase.FIRInstallations"; + +@interface FIRInstallationsStore () +@property(nonatomic, readonly) GULKeychainStorage *secureStorage; +@property(nonatomic, readonly, nullable) NSString *accessGroup; +@property(nonatomic, readonly) dispatch_queue_t queue; +@property(nonatomic, readonly) GULUserDefaults *userDefaults; +@end + +@implementation FIRInstallationsStore + +- (instancetype)initWithSecureStorage:(GULKeychainStorage *)storage + accessGroup:(NSString *)accessGroup { + self = [super init]; + if (self) { + _secureStorage = storage; + _accessGroup = [accessGroup copy]; + _queue = dispatch_queue_create("com.firebase.FIRInstallationsStore", DISPATCH_QUEUE_SERIAL); + + NSString *userDefaultsSuiteName = _accessGroup ?: kFIRInstallationsStoreUserDefaultsID; + _userDefaults = [[GULUserDefaults alloc] initWithSuiteName:userDefaultsSuiteName]; + } + return self; +} + +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName { + NSString *itemID = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self installationExistsForAppID:appID appName:appName] + .then(^id(id result) { + return [self.secureStorage getObjectForKey:itemID + objectClass:[FIRInstallationsStoredItem class] + accessGroup:self.accessGroup]; + }) + .then(^id(FIRInstallationsStoredItem *_Nullable storedItem) { + if (storedItem == nil) { + return [FIRInstallationsErrorUtil installationItemNotFoundForAppID:appID appName:appName]; + } + + FIRInstallationsItem *item = [[FIRInstallationsItem alloc] initWithAppID:appID + firebaseAppName:appName]; + [item updateWithStoredItem:storedItem]; + return item; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem { + FIRInstallationsStoredItem *storedItem = [installationItem storedItem]; + NSString *identifier = [installationItem identifier]; + + return + [self.secureStorage setObject:storedItem forKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:YES forItemWithIdentifier:identifier]; + }); +} + +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self.secureStorage removeObjectForKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:NO forItemWithIdentifier:identifier]; + }); +} + +#pragma mark - User defaults + +- (FBLPromise *)installationExistsForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + return [[self userDefaults] objectForKey:identifier] != nil + ? [NSNull null] + : [FIRInstallationsErrorUtil + installationItemNotFoundForAppID:appID + appName:appName]; + }]; +} + +- (FBLPromise *)setInstallationExists:(BOOL)exists + forItemWithIdentifier:(NSString *)identifier { + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + if (exists) { + [[self userDefaults] setBool:YES forKey:identifier]; + } else { + [[self userDefaults] removeObjectForKey:identifier]; + } + + return [NSNull null]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h new file mode 100644 index 00000000..f6e42828 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The enum represent possible states of the installation auth token. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredAuthToken`. + * Modification of it can lead to incompatibility with previous version. Any modification must be + * evaluated and, if it is really needed, the `storageVersion` must be bumped and proper migration + * code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenStatus) { + /// An initial status or an undefined value. + FIRInstallationsAuthTokenStatusUnknown, + /// The auth token has been received from the server. + FIRInstallationsAuthTokenStatusTokenReceived +}; + +/** + * This class serializes and deserializes the installation data into/from `NSData` to be stored in + * Keychain. This class is primarily used by `FIRInstallationsStore`. It is also used on the logic + * level as a data object (see `FIRInstallationsItem.authToken`). + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredAuthToken : NSObject +@property FIRInstallationsAuthTokenStatus status; + +/// The token that can be used to authorize requests to Firebase backend. +@property(nullable, copy) NSString *token; +/// The date when the auth token expires. +@property(nullable, copy) NSDate *expirationDate; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m new file mode 100644 index 00000000..b21f6dd2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredAuthToken.h" + +#import "FIRInstallationsLogger.h" + +NSString *const kFIRInstallationsStoredAuthTokenStatusKey = @"status"; +NSString *const kFIRInstallationsStoredAuthTokenTokenKey = @"token"; +NSString *const kFIRInstallationsStoredAuthTokenExpirationDateKey = @"expirationDate"; +NSString *const kFIRInstallationsStoredAuthTokenStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredAuthTokenStorageVersion = 1; + +@implementation FIRInstallationsStoredAuthToken + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredAuthTokenStorageVersion; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsStoredAuthToken *clone = [[FIRInstallationsStoredAuthToken alloc] init]; + clone.status = self.status; + clone.token = [self.token copy]; + clone.expirationDate = self.expirationDate; + return clone; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeInteger:self.status forKey:kFIRInstallationsStoredAuthTokenStatusKey]; + [aCoder encodeObject:self.token forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + [aCoder encodeObject:self.expirationDate + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + [aCoder encodeInteger:self.storageVersion + forKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; + if (storageVersion > kFIRInstallationsStoredAuthTokenStorageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch, + @"FIRInstallationsStoredAuthToken was encoded by a newer coder version %ld. " + @"Current coder version is %ld. Some auth token data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredAuthTokenStorageVersion); + } + + FIRInstallationsStoredAuthToken *object = [[FIRInstallationsStoredAuthToken alloc] init]; + object.status = [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStatusKey]; + object.token = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + object.expirationDate = + [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + + return object; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h new file mode 100644 index 00000000..4926588c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class is supposed to be used by `FIRInstallationsStore` only. It is required to + * serialize/deserialize the installation data into/from `NSData` to be stored in Keychain. + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredItem : NSObject + +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic) FIRInstallationsStatus registrationStatus; + +/// Instance ID default auth token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m new file mode 100644 index 00000000..0c7655c3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredItem.h" + +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" + +NSString *const kFIRInstallationsStoredItemFirebaseInstallationIDKey = @"firebaseInstallationID"; +NSString *const kFIRInstallationsStoredItemRefreshTokenKey = @"refreshToken"; +NSString *const kFIRInstallationsStoredItemAuthTokenKey = @"authToken"; +NSString *const kFIRInstallationsStoredItemRegistrationStatusKey = @"registrationStatus"; +NSString *const kFIRInstallationsStoredItemIIDDefaultTokenKey = @"IIDDefaultToken"; +NSString *const kFIRInstallationsStoredItemStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredItemStorageVersion = 1; + +@implementation FIRInstallationsStoredItem + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredItemStorageVersion; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:self.firebaseInstallationID + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + [aCoder encodeObject:self.refreshToken forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + [aCoder encodeObject:self.authToken forKey:kFIRInstallationsStoredItemAuthTokenKey]; + [aCoder encodeInteger:self.registrationStatus + forKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + [aCoder encodeObject:self.IIDDefaultToken forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + [aCoder encodeInteger:self.storageVersion forKey:kFIRInstallationsStoredItemStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemStorageVersionKey]; + if (storageVersion > self.storageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInstallationCoderVersionMismatch, + @"FIRInstallationsStoredItem was encoded by a newer coder version %ld. Current " + @"coder version is %ld. Some installation data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredItemStorageVersion); + } + + FIRInstallationsStoredItem *item = [[FIRInstallationsStoredItem alloc] init]; + item.firebaseInstallationID = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + item.refreshToken = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + item.authToken = [aDecoder decodeObjectOfClass:[FIRInstallationsStoredAuthToken class] + forKey:kFIRInstallationsStoredItemAuthTokenKey]; + item.registrationStatus = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + item.IIDDefaultToken = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + + return item; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h new file mode 100644 index 00000000..4839b4e0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRInstallationsAuthTokenResult; + +NS_ASSUME_NONNULL_BEGIN + +/** A notification with this name is sent each time an installation is created or deleted. */ +FOUNDATION_EXPORT const NSNotificationName FIRInstallationIDDidChangeNotification; +/** `userInfo` key for the `FirebaseApp.name` in `FIRInstallationIDDidChangeNotification`. */ +FOUNDATION_EXPORT NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey; + +/** + * An installation ID handler block. + * @param identifier The installation ID string if exists or `nil` otherwise. + * @param error The error when `identifier == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsIDHandler)(NSString *__nullable identifier, + NSError *__nullable error) + NS_SWIFT_NAME(InstallationsIDHandler); + +/** + * An authorization token handler block. + * @param tokenResult An instance of `InstallationsAuthTokenResult` in case of success or `nil` + * otherwise. + * @param error The error when `tokenResult == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsTokenHandler)( + FIRInstallationsAuthTokenResult *__nullable tokenResult, NSError *__nullable error) + NS_SWIFT_NAME(InstallationsTokenHandler); + +/** + * The class provides API for Firebase Installations. + * Each configured `FirebaseApp` has a corresponding single instance of `Installations`. + * An instance of the class provides access to the installation info for the `FirebaseApp` as well + * as the ability to delete it. A Firebase Installation is unique by `FirebaseApp.name` and + * `FirebaseApp.options.googleAppID` . + */ +NS_SWIFT_NAME(Installations) +@interface FIRInstallations : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Returns a default instance of `Installations`. + * @returns An instance of `Installations` for `FirebaseApp.defaultApp(). + * @throw Throws an exception if the default app is not configured yet or required `FirebaseApp` + * options are missing. + */ ++ (FIRInstallations *)installations NS_SWIFT_NAME(installations()); + +/** + * Returns an instance of `Installations` for an application. + * @param application A configured `FirebaseApp` instance. + * @returns An instance of `Installations` corresponding to the passed application. + * @throw Throws an exception if required `FirebaseApp` options are missing. + */ ++ (FIRInstallations *)installationsWithApp:(FIRApp *)application NS_SWIFT_NAME(installations(app:)); + +/** + * The method creates or retrieves an installation ID. The installation ID is a stable identifier + * that uniquely identifies the app instance. NOTE: If the application already has an existing + * FirebaseInstanceID then the InstanceID identifier will be used. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsIDHandler` for additional details. + */ +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion; + +/** + * Retrieves (locally if it exists or from the server) a valid authorization token. An existing + * token may be invalidated or expired, so it is recommended to fetch the auth token before each + * server request. The method does the same as `Installations.authTokenForcingRefresh(:, + * completion:)` with forcing refresh `NO`. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion; + +/** + * Retrieves (locally or from the server depending on `forceRefresh` value) a valid authorization + * token. An existing token may be invalidated or expire, so it is recommended to fetch the auth + * token before each server request. This method should be used with `forceRefresh == YES` when e.g. + * a request with the previously fetched auth token failed with "Not Authorized" error. + * @param forceRefresh If `YES` then the locally cached auth token will be ignored and a new one + * will be requested from the server. If `NO`, then the locally cached auth token will be returned + * if exists and has not expired yet. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion; + +/** + * Deletes all the installation data including the unique identifier, auth tokens and + * all related data on the server side. A network connection is required for the method to + * succeed. If fails, the existing installation data remains untouched. + * @param completion A completion handler which is invoked when the operation completes. `error == + * nil` indicates success. + */ +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h new file mode 100644 index 00000000..7753132d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class represents a result of the auth token request. */ +NS_SWIFT_NAME(InstallationsAuthTokenResult) +@interface FIRInstallationsAuthTokenResult : NSObject + +/** The authorization token string. */ +@property(nonatomic, readonly) NSString *authToken; + +/** The auth token expiration date. */ +@property(nonatomic, readonly) NSDate *expirationDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h new file mode 100644 index 00000000..d0c3b996 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *const kFirebaseInstallationsErrorDomain; + +typedef NS_ENUM(NSUInteger, FIRInstallationsErrorCode) { + /** Unknown error. See `userInfo` for details. */ + FIRInstallationsErrorCodeUnknown = 0, + + /** Keychain error. See `userInfo` for details. */ + FIRInstallationsErrorCodeKeychain = 1, + + /** Server unreachable. A network error or server is unavailable. See `userInfo` for details. */ + FIRInstallationsErrorCodeServerUnreachable = 2, + + /** FirebaseApp configuration issues e.g. invalid GMP-App-ID, etc. See `userInfo` for details. */ + FIRInstallationsErrorCodeInvalidConfiguration = 3, + +} NS_SWIFT_NAME(InstallationsErrorCode); diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h new file mode 100644 index 00000000..8cdf6778 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h @@ -0,0 +1,19 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT const char *const FIRInstallationsVersionStr; diff --git a/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h new file mode 100644 index 00000000..accc9ac6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h @@ -0,0 +1,20 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" diff --git a/MyExperiences copy/Pods/FirebaseInstallations/LICENSE b/MyExperiences copy/Pods/FirebaseInstallations/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseInstallations/README.md b/MyExperiences copy/Pods/FirebaseInstallations/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseInstallations/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRAppInternal.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponent.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentContainer.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentType.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRDependency.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrorCode.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrors.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLibrary.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLogger.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIROptionsInternal.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m new file mode 100644 index 00000000..c407272a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m @@ -0,0 +1,260 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +#import "FirebaseStorage/Sources/FIRStorageComponent.h" +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStoragePath.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Auth/Public/FIRAuthInterop.h" + +#import +#import + +static NSMutableDictionary< + NSString * /* app name */, + NSMutableDictionary *> *_fetcherServiceMap; +static GTMSessionFetcherRetryBlock _retryWhenOffline; + +@interface FIRStorage () { + /// Stored Auth reference, if it exists. This needs to be stored for `copyWithZone:`. + id _Nullable _auth; +} +@end + +@implementation FIRStorage + ++ (void)initialize { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _retryWhenOffline = ^(BOOL suggestedWillRetry, NSError *GTM_NULLABLE_TYPE error, + GTMSessionFetcherRetryResponse response) { + bool shouldRetry = suggestedWillRetry; + // GTMSessionFetcher does not consider being offline a retryable error, but we do, so we + // special-case it here. + if (!shouldRetry && error) { + shouldRetry = error.code == NSURLErrorNotConnectedToInternet; + } + response(shouldRetry); + }; + _fetcherServiceMap = [[NSMutableDictionary alloc] init]; + }); +} + ++ (GTMSessionFetcherService *)fetcherServiceForApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth { + @synchronized(_fetcherServiceMap) { + NSMutableDictionary *bucketMap = _fetcherServiceMap[app.name]; + if (!bucketMap) { + bucketMap = [[NSMutableDictionary alloc] init]; + _fetcherServiceMap[app.name] = bucketMap; + } + + GTMSessionFetcherService *fetcherService = bucketMap[bucket]; + if (!fetcherService) { + fetcherService = [[GTMSessionFetcherService alloc] init]; + [fetcherService setRetryEnabled:YES]; + [fetcherService setRetryBlock:_retryWhenOffline]; + FIRStorageTokenAuthorizer *authorizer = + [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:app.options.googleAppID + fetcherService:fetcherService + authProvider:auth]; + [fetcherService setAuthorizer:authorizer]; + bucketMap[bucket] = fetcherService; + } + return fetcherService; + } +} + ++ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled { + [GTMSessionFetcher setLoggingEnabled:isLoggingEnabled]; +} + ++ (instancetype)storage { + return [self storageForApp:[FIRApp defaultApp]]; +} + ++ (instancetype)storageForApp:(FIRApp *)app { + if (app.options.storageBucket) { + NSString *url = [app.options.storageBucket isEqualToString:@""] + ? @"" + : [@"gs://" stringByAppendingString:app.options.storageBucket]; + return [self storageForApp:app URL:url]; + } else { + NSString *const kAppNotConfiguredMessage = + @"No default Storage bucket found. Did you configure Firebase Storage properly?"; + [NSException raise:NSInvalidArgumentException format:kAppNotConfiguredMessage]; + return nil; + } +} + ++ (instancetype)storageWithURL:(NSString *)url { + return [self storageForApp:[FIRApp defaultApp] URL:url]; +} + ++ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url { + NSString *bucket; + if ([url isEqualToString:@""]) { + bucket = @""; + } else { + FIRStoragePath *path; + + @try { + path = [FIRStoragePath pathFromGSURI:url]; + } @catch (NSException *e) { + [NSException raise:NSInternalInconsistencyException + format:@"URI must be in the form of gs:///"]; + } + + if (path.object != nil && ![path.object isEqualToString:@""]) { + [NSException raise:NSInternalInconsistencyException + format:@"Storage bucket cannot be initialized with a path"]; + } + + bucket = path.bucket; + } + + // Retrieve the instance provider from the app's container to inject dependencies as needed. + id provider = + FIR_COMPONENT(FIRStorageMultiBucketProvider, app.container); + return [provider storageForBucket:bucket]; +} + +- (instancetype)initWithApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth { + self = [super init]; + if (self) { + _app = app; + _auth = auth; + _storageBucket = bucket; + _dispatchQueue = dispatch_queue_create("com.google.firebase.storage", DISPATCH_QUEUE_SERIAL); + _fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app bucket:bucket auth:auth]; + _maxDownloadRetryTime = 600.0; + _maxOperationRetryTime = 120.0; + _maxUploadRetryTime = 600.0; + } + return self; +} + +- (instancetype)init { + NSAssert(false, @"Storage cannot be directly instantiated, use " + "Storage.storage() or Storage.storage(app:) instead"); + return nil; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorage *storage = [[[self class] allocWithZone:zone] initWithApp:_app + bucket:_storageBucket + auth:_auth]; + storage.callbackQueue = self.callbackQueue; + return storage; +} + +// Two FIRStorage objects are equal if they use the same app +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorage class]]) { + return NO; + } + + BOOL isEqualObject = [self isEqualToFIRStorage:(FIRStorage *)object]; + return isEqualObject; +} + +- (BOOL)isEqualToFIRStorage:(FIRStorage *)storage { + BOOL isEqual = + [_app isEqual:storage.app] && [_storageBucket isEqualToString:storage.storageBucket]; + return isEqual; +} + +- (NSUInteger)hash { + NSUInteger hash = [_app hash] ^ [self.callbackQueue hash]; + return hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, _app]; +} + +#pragma mark - Public methods + +- (FIRStorageReference *)reference { + FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:_storageBucket object:nil]; + return [[FIRStorageReference alloc] initWithStorage:self path:path]; +} + +- (FIRStorageReference *)referenceForURL:(NSString *)string { + FIRStoragePath *path = [FIRStoragePath pathFromString:string]; + + // If no default bucket exists (empty string), accept anything. + if ([_storageBucket isEqual:@""]) { + FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path]; + return reference; + } + + // If there exists a default bucket, throw if provided a different bucket. + if (![path.bucket isEqual:_storageBucket]) { + NSString *const kInvalidBucketFormat = + @"Provided bucket: %@ does not match the Storage bucket of the current instance: %@"; + [NSException raise:NSInvalidArgumentException + format:kInvalidBucketFormat, path.bucket, _storageBucket]; + } + + FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path]; + return reference; +} + +- (FIRStorageReference *)referenceWithPath:(NSString *)string { + FIRStorageReference *reference = [[self reference] child:string]; + return reference; +} + +- (dispatch_queue_t)callbackQueue { + return _fetcherServiceForApp.callbackQueue; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + _fetcherServiceForApp.callbackQueue = callbackQueue; +} + +#pragma mark - Background tasks + ++ (void)enableBackgroundTasks:(BOOL)isEnabled { + [NSException raise:NSGenericException format:@"enableBackgroundTasks not implemented"]; +} + +- (NSArray *)uploadTasks { + [NSException raise:NSGenericException format:@"getUploadTasks not implemented"]; + return nil; +} + +- (NSArray *)downloadTasks { + [NSException raise:NSGenericException format:@"getDownloadTasks not implemented"]; + return nil; +} +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h new file mode 100644 index 00000000..ac3637ba --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h @@ -0,0 +1,45 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class FIRApp; +@class FIRStorage; + +NS_ASSUME_NONNULL_BEGIN + +/// This protocol is used in the interop registration process to register an instance provider for +/// individual FIRApps. +@protocol FIRStorageMultiBucketProvider + +/// Default method for creating a Storage instance. +- (FIRStorage *)storageForBucket:(NSString *)bucket; + +@end + +/// A concrete implementation for FIRStorageMultiBucketProvider to create Storage instances. +@interface FIRStorageComponent : NSObject + +/// The FIRApp that instances will be set up with. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Default method for creating a Storage instance. +- (FIRStorage *)storageForBucket:(NSString *)bucket; + +/// Unavailable, use `storageForApp:storageURL:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m new file mode 100644 index 00000000..201021a8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m @@ -0,0 +1,84 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageComponent.h" + +#import + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "Interop/Auth/Public/FIRAuthInterop.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorage () +// Surface the internal initializer to create instances of FIRStorage. +- (instancetype)initWithApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth; +@end + +@interface FIRStorageComponent () +/// Internal initializer. +- (instancetype)initWithApp:(FIRApp *)app; +@end + +@implementation FIRStorageComponent + +#pragma mark - Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + self = [super init]; + if (self) { + _app = app; + } + return self; +} + +#pragma mark - Lifecycle + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-str" + withVersion:[NSString stringWithUTF8String:FIRStorageVersionString]]; +} + +#pragma mark - FIRComponentRegistrant + ++ (nonnull NSArray *)componentsToRegister { + FIRDependency *authDep = [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop) + isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + return [[FIRStorageComponent alloc] initWithApp:container.app]; + }; + FIRComponent *storageProvider = + [FIRComponent componentWithProtocol:@protocol(FIRStorageMultiBucketProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ authDep ] + creationBlock:creationBlock]; + + return @[ storageProvider ]; +} + +#pragma mark - FIRStorageInstanceProvider Conformance + +- (FIRStorage *)storageForBucket:(NSString *)bucket { + // Create an instance of FIRStorage and return it. + id auth = FIR_COMPONENT(FIRAuthInterop, self.app.container); + return [[FIRStorage alloc] initWithApp:self.app bucket:bucket auth:auth]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m new file mode 100644 index 00000000..11dbfa00 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m @@ -0,0 +1,92 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +NSString *const kGCSScheme = @"https"; +NSString *const kGCSHost = @"www.googleapis.com"; +NSString *const kGCSUploadPath = @"upload"; +NSString *const kGCSStorageVersionPath = @"storage/v1"; +NSString *const kGCSBucketPathFormat = @"b/%@"; +NSString *const kGCSObjectPathFormat = @"o/%@"; + +NSString *const kFIRStorageScheme = @"https"; +NSString *const kFIRStorageHost = @"firebasestorage.googleapis.com"; +NSString *const kFIRStorageVersionPath = @"v0"; +NSString *const kFIRStorageBucketPathFormat = @"b/%@"; +NSString *const kFIRStorageObjectPathFormat = @"o/%@"; +NSString *const kFIRStorageFullPathFormat = @"/v0/b/%@/o/%@"; + +NSString *const kFIRStorageAuthTokenFormat = @"Firebase %@"; +NSString *const kFIRStorageDefaultBucketFormat = @"gs://%@"; + +NSString *const kFIRStorageResponseErrorDomain = @"ResponseErrorDomain"; +NSString *const kFIRStorageResponseErrorCode = @"ResponseErrorCode"; +NSString *const kFIRStorageResponseBody = @"ResponseBody"; + +NSString *const FIRStorageErrorDomain = @"FIRStorageErrorDomain"; + +NSString *const kFIRStorageInvalidDataFormat = @"Invalid data returned from the server: %@"; +NSString *const kFIRStorageInvalidObserverStatus = + @"Invalid observer status requested, use one " + @"of: FIRStorageTaskStatusPause, Resume, Progress, " + @"Complete, or Failure"; + +/** + * String constants mapping GCS Object#list results to ListResult fields. + */ +NSString *const kFIRStorageListPrefixes = @"prefixes"; +NSString *const kFIRStorageListItems = @"items"; +NSString *const kFIRStorageListItemName = @"name"; +NSString *const kFIRStorageListPageToken = @"nextPageToken"; + +/** + * String constants mapping GCS Object#resource mappings to metadata fields. + */ +NSString *const kFIRStorageMetadataBucket = @"bucket"; +NSString *const kFIRStorageMetadataCacheControl = @"cacheControl"; +NSString *const kFIRStorageMetadataContentDisposition = @"contentDisposition"; +NSString *const kFIRStorageMetadataContentEncoding = @"contentEncoding"; +NSString *const kFIRStorageMetadataContentLanguage = @"contentLanguage"; +NSString *const kFIRStorageMetadataContentType = @"contentType"; +NSString *const kFIRStorageMetadataCustomMetadata = @"metadata"; +NSString *const kFIRStorageMetadataSize = @"size"; +NSString *const kFIRStorageMetadataGeneration = @"generation"; +NSString *const kFIRStorageMetadataMetageneration = @"metageneration"; +NSString *const kFIRStorageMetadataTimeCreated = @"timeCreated"; +NSString *const kFIRStorageMetadataUpdated = @"updated"; +NSString *const kFIRStorageMetadataName = @"name"; +NSString *const kFIRStorageMetadataDownloadTokens = @"downloadTokens"; +NSString *const kFIRStorageMetadataMd5Hash = @"md5Hash"; + +// TODO: add notification support +NSString *const kFIRStorageTaskStatusResumeNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusPauseNotification = @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusProgressNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusCompleteNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusFailureNotification = + @"kFIRStorageTaskStatusResumeNotification"; + +NSString *const kFIRStorageBundleIdentifier = @"com.google.firebase.storage"; + +// The STR and STR_EXPAND macro allow a numeric version passed to he compiler driver +// with a -D to be treated as a string instead of an invalid floating point value. +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +const char *const FIRStorageVersionString = (const char *const)STR(FIRStorage_VERSION); diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h new file mode 100644 index 00000000..76c382d8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h @@ -0,0 +1,150 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageMetadata; + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kGCSScheme; +FOUNDATION_EXPORT NSString *const kGCSHost; +FOUNDATION_EXPORT NSString *const kGCSUploadPath; +FOUNDATION_EXPORT NSString *const kGCSStorageVersionPath; +FOUNDATION_EXPORT NSString *const kGCSBucketPathFormat; +FOUNDATION_EXPORT NSString *const kGCSObjectPathFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageScheme; +FOUNDATION_EXPORT NSString *const kFIRStorageHost; +FOUNDATION_EXPORT NSString *const kFIRStorageVersionPath; +FOUNDATION_EXPORT NSString *const kFIRStorageBucketPathFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageObjectPathFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageFullPathFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageAuthTokenFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageDefaultBucketFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorDomain; +FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorCode; +FOUNDATION_EXPORT NSString *const kFIRStorageResponseBody; + +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusResumeNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusPauseNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusProgressNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusCompleteNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusFailureNotification; + +FOUNDATION_EXPORT NSString *const kFIRStorageListPrefixes; +FOUNDATION_EXPORT NSString *const kFIRStorageListItems; +FOUNDATION_EXPORT NSString *const kFIRStorageListItemName; +FOUNDATION_EXPORT NSString *const kFIRStorageListPageToken; + +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataBucket; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCacheControl; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentDisposition; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentEncoding; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentLanguage; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentType; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCustomMetadata; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataSize; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataGeneration; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMetageneration; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataTimeCreated; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataUpdated; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataName; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataDownloadTokens; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMd5Hash; + +FOUNDATION_EXPORT NSString *const kFIRStorageInvalidDataFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageInvalidObserverStatus; + +FOUNDATION_EXPORT NSString *const kFIRStorageBundleIdentifier; + +/** + * Enum representing the internal state of an upload or download task. + */ +typedef NS_ENUM(NSInteger, FIRStorageTaskState) { + /** + * Unknown task state + */ + FIRStorageTaskStateUnknown, + + /** + * Task is being queued is ready to run + */ + FIRStorageTaskStateQueueing, + + /** + * Task is resuming from a paused state + */ + FIRStorageTaskStateResuming, + + /** + * Task is currently running + */ + FIRStorageTaskStateRunning, + + /** + * Task reporting a progress event + */ + FIRStorageTaskStateProgress, + + /** + * Task is pausing + */ + FIRStorageTaskStatePausing, + + /** + * Task is completing successfully + */ + FIRStorageTaskStateCompleting, + + /** + * Task is failing unrecoverably + */ + FIRStorageTaskStateFailing, + + /** + * Task paused successfully + */ + FIRStorageTaskStatePaused, + + /** + * Task cancelled successfully + */ + FIRStorageTaskStateCancelled, + + /** + * Task completed successfully + */ + FIRStorageTaskStateSuccess, + + /** + * Task failed unrecoverably + */ + FIRStorageTaskStateFailed +}; + +/** + * Represents the various types of metadata: Files or Folders. + */ +typedef NS_ENUM(NSUInteger, FIRStorageMetadataType) { + FIRStorageMetadataTypeUnknown, + FIRStorageMetadataTypeFile, + FIRStorageMetadataTypeFolder, +}; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h new file mode 100644 index 00000000..02fcf62c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to delete an object in Firebase Storage. + */ +@interface FIRStorageDeleteTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m new file mode 100644 index 00000000..1bb443e8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m @@ -0,0 +1,83 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageDeleteTask.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageDeleteTask { + @private + FIRStorageVoidError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)enqueue { + __weak FIRStorageDeleteTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageDeleteTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"DELETE"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + + fetcher.comment = @"DeleteTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + if (callback) { + callback(self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diangostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m new file mode 100644 index 00000000..c551c3ca --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m @@ -0,0 +1,189 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageDownloadTask + +@synthesize progress = _progress; +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(nullable NSURL *)fileURL { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _fileURL = [fileURL copy]; + _progress = [NSProgress progressWithTotalUnitCount:0]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + [self enqueueWithData:nil]; +} + +- (void)enqueueWithData:(nullable NSData *)resumeData { + __weak FIRStorageDownloadTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageDownloadTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + strongSelf.state = FIRStorageTaskStateQueueing; + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxDownloadRetryTime; + NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL + resolvingAgainstBaseURL:NO]; + [components setQuery:@"alt=media"]; + request.URL = components.URL; + + GTMSessionFetcher *fetcher; + if (resumeData) { + fetcher = [GTMSessionFetcher fetcherWithDownloadResumeData:resumeData]; + fetcher.comment = @"Resuming DownloadTask"; + } else { + fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + fetcher.comment = @"Starting DownloadTask"; + } + + [fetcher setResumeDataBlock:^(NSData *data) { + FIRStorageDownloadTask *strong = weakSelf; + if (strong && data) { + strong->_downloadData = data; + } + }]; + + fetcher.maxRetryInterval = strongSelf.reference.storage.maxDownloadRetryTime; + + if (strongSelf->_fileURL) { + // Handle file downloads + [fetcher setDestinationFileURL:strongSelf->_fileURL]; + [fetcher setDownloadProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesWritten; + weakSelf.progress.totalUnitCount = totalBytesExpectedToWrite; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + } else { + // Handle data downloads + [fetcher setReceivedProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesWritten; + int64_t totalLength = [[weakSelf.fetcher response] expectedContentLength]; + weakSelf.progress.totalUnitCount = totalLength; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + } + + strongSelf->_fetcher = fetcher; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + // Fire last progress updates + [self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot]; + + // Handle potential issues with download + if (error) { + self.state = FIRStorageTaskStateFailed; + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + [self fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; + return; + } + + // Download completed successfully, fire completion callbacks + self.state = FIRStorageTaskStateSuccess; + + if (data) { + self->_downloadData = data; + } + + [self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + strongSelf.state = FIRStorageTaskStateRunning; + [strongSelf.fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +#pragma mark - Download Management + +- (void)cancel { + NSError *error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled]; + [self cancelWithError:error]; +} + +- (void)cancelWithError:(NSError *)error { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateCancelled; + [weakSelf.fetcher stopFetching]; + weakSelf.error = error; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot]; + }]; +} + +- (void)pause { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStatePausing; + [weakSelf.fetcher stopFetching]; + // Give the resume callback a chance to run (if scheduled) + [weakSelf.fetcher waitForCompletionWithTimeout:0.001]; + weakSelf.state = FIRStorageTaskStatePaused; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:snapshot]; + }]; +} + +- (void)resume { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateResuming; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + [weakSelf enqueueWithData:weakSelf.downloadData]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h new file mode 100644 index 00000000..1b682050 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class FIRStorageReference; +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageDownloadTask () + +/** + * Bytes which have been downloaded so far. + */ +@property(readonly, nonatomic) NSData *downloadData; + +/** + * The file on disk to write to. + */ +@property(copy, nonatomic) NSURL *fileURL; + +/** + * Initializes a download task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param fileURL The system URL to download to. If nil, download in memory as bytes. + * @return Returns an instance of FIRStorageDownloadTask + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(nullable NSURL *)fileURL; + +/** + * Cancels the download task and passes an appropriate error to the developer. + * @param error NSError to propegate to the developer. + */ +- (void)cancelWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h new file mode 100644 index 00000000..99648c11 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; + +/** + * Adds wrappers for common Firebase Storage errors (including creating errors from GCS errors). + * For more information on unwrapping GCS errors, see the GCS errors docs: + * https://cloud.google.com/storage/docs/json_api/v1/status-codes + * This is never publicly exposed to end developers (as they will simply see an NSError). + */ +@interface FIRStorageErrors : NSObject + +/** + * Creates a Firebase Storage error from a specific FIRStorageErrorCode. + */ ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code; + +/** + * Creates a Firebase Storage error from a specific FIRStorageErrorCode while adding + * custom info from an optionally provided info dictionary. + */ ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code + infoDictionary:(nullable NSDictionary *)dictionary; + +/** + * Creates a Firebase Storage error from a specific GCS error and FIRStorageReference. + * @param error Server error to wrap and return as a Firebase Storage error. + * @param reference FIRStorageReference which provides context about the request being made. + * @return Returns a Firebase Storage error, or nil if no error is provided. + */ ++ (nullable NSError *)errorWithServerError:(nullable NSError *)error + reference:(nullable FIRStorageReference *)reference; + +/** + * Creates a Firebase Storage error from an invalid request. + * + * @param request The NSData representation of the invalid user request. + * @return Returns the corresponding Firebase Storage error. + */ ++ (NSError *)errorWithInvalidRequest:(NSData *)request; + +/** + * Creates a Firebase Storage error with a custom error message. + * + * @param errorMessage A custom error message. + * @return Returns the corresponding Firebase Storage error. + */ ++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m new file mode 100644 index 00000000..1301d062 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m @@ -0,0 +1,189 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageErrors.h" + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" + +@implementation FIRStorageErrors + ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code { + return [FIRStorageErrors errorWithCode:code infoDictionary:nil]; +} + ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code + infoDictionary:(nullable NSDictionary *)dictionary { + NSMutableDictionary *errorDictionary; + if (dictionary) { + errorDictionary = [dictionary mutableCopy]; + } else { + errorDictionary = [[NSMutableDictionary alloc] init]; + } + + NSString *errorMessage; + switch (code) { + case FIRStorageErrorCodeObjectNotFound: + errorMessage = + [NSString stringWithFormat:@"Object %@ does not exist.", errorDictionary[@"object"]]; + break; + + case FIRStorageErrorCodeBucketNotFound: + errorMessage = + [NSString stringWithFormat:@"Bucket %@ does not exist.", errorDictionary[@"bucket"]]; + break; + + case FIRStorageErrorCodeProjectNotFound: + errorMessage = + [NSString stringWithFormat:@"Project %@ does not exist.", errorDictionary[@"project"]]; + break; + + case FIRStorageErrorCodeQuotaExceeded: { + NSString *const kQuotaExceededFormat = + @"Quota for bucket %@ exceeded, please view quota on firebase.google.com."; + errorMessage = [NSString stringWithFormat:kQuotaExceededFormat, errorDictionary[@"bucket"]]; + break; + } + + case FIRStorageErrorCodeDownloadSizeExceeded: { + int64_t total = [errorDictionary[@"totalSize"] longLongValue]; + int64_t size = [errorDictionary[@"maxAllowedSize"] longLongValue]; + NSString *totalString = total ? @(total).stringValue : @"unknown"; + NSString *sizeString = total ? @(size).stringValue : @"unknown"; + NSString *const kSizeExceededErrorFormat = + @"Attempted to download object with size of %@ bytes, " + @"which exceeds the maximum size of %@ bytes. " + @"Consider raising the maximum download size, or using " + @"[FIRStorageReference writeToFile:]"; + errorMessage = [NSString stringWithFormat:kSizeExceededErrorFormat, totalString, sizeString]; + break; + } + + case FIRStorageErrorCodeUnauthenticated: + errorMessage = @"User is not authenticated, please authenticate using Firebase " + @"Authentication and try again."; + break; + + case FIRStorageErrorCodeUnauthorized: { + NSString *bucket = errorDictionary[@"bucket"]; + NSString *object = errorDictionary[@"object"]; + NSString *const kUnauthorizedFormat = @"User does not have permission to access gs://%@/%@."; + errorMessage = [NSString stringWithFormat:kUnauthorizedFormat, bucket, object]; + break; + } + + case FIRStorageErrorCodeRetryLimitExceeded: + errorMessage = @"Max retry time for operation exceeded, please try again."; + break; + + case FIRStorageErrorCodeNonMatchingChecksum: { + // TODO: replace with actual checksum strings when we choose to implement. + NSString *const kChecksumFailedErrorFormat = + @"Uploaded/downloaded object %@ has checksum: %@ " + @"which does not match server checksum: %@. Please retry the upload/download."; + errorMessage = [NSString stringWithFormat:kChecksumFailedErrorFormat, @"object", + @"client checksum", @"server checksum"]; + break; + } + + case FIRStorageErrorCodeCancelled: + errorMessage = @"User cancelled the upload/download."; + break; + + case FIRStorageErrorCodeUnknown: + /* Fall through to default case for unknown errors */ + + default: + errorMessage = @"An unknown error occurred, please check the server response."; + break; + } + + errorDictionary[NSLocalizedDescriptionKey] = errorMessage; + + NSError *err = [NSError errorWithDomain:FIRStorageErrorDomain code:code userInfo:errorDictionary]; + return err; +} + ++ (nullable NSError *)errorWithServerError:(nullable NSError *)error + reference:(nullable FIRStorageReference *)reference { + if (error == nil) { + return nil; + } + + FIRStorageErrorCode errorCode; + switch (error.code) { + case 400: + errorCode = FIRStorageErrorCodeUnknown; + break; + + case 401: + errorCode = FIRStorageErrorCodeUnauthenticated; + break; + + case 402: + errorCode = FIRStorageErrorCodeQuotaExceeded; + break; + + case 403: + errorCode = FIRStorageErrorCodeUnauthorized; + break; + + case 404: + errorCode = FIRStorageErrorCodeObjectNotFound; + break; + + default: + errorCode = FIRStorageErrorCodeUnknown; + break; + } + + NSMutableDictionary *errorDictionary = + [[[NSDictionary alloc] initWithDictionary:error.userInfo] mutableCopy]; + errorDictionary[kFIRStorageResponseErrorDomain] = error.domain; + errorDictionary[kFIRStorageResponseErrorCode] = @(error.code); + + // Turn raw response into a string + NSData *responseData = errorDictionary[@"data"]; + if (responseData) { + NSString *errorString = [[NSString alloc] initWithData:responseData + encoding:NSUTF8StringEncoding]; + errorDictionary[kFIRStorageResponseBody] = errorString ?: @"No Response from Server."; + } + + errorDictionary[@"bucket"] = reference.path.bucket; + errorDictionary[@"object"] = reference.path.object; + + NSError *clientError = [FIRStorageErrors errorWithCode:errorCode infoDictionary:errorDictionary]; + return clientError; +} + ++ (NSError *)errorWithInvalidRequest:(NSData *)request { + NSString *requestString = [[NSString alloc] initWithData:request encoding:NSUTF8StringEncoding]; + NSString *invalidDataString = + [NSString stringWithFormat:kFIRStorageInvalidDataFormat, requestString]; + NSDictionary *dict; + if (invalidDataString.length > 0) { + dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; + } + return [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; +} + ++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage { + return [NSError errorWithDomain:FIRStorageErrorDomain + code:FIRStorageErrorCodeUnknown + userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h new file mode 100644 index 00000000..06116956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get a download URL for an object in Firebase Storage. + */ +@interface FIRStorageGetDownloadURLTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidURLError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m new file mode 100644 index 00000000..f7422b26 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m @@ -0,0 +1,126 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageGetDownloadURLTask { + @private + FIRStorageVoidURLError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidURLError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + ++ (NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary { + NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens]; + + if (downloadTokens && downloadTokens.length > 0) { + NSArray *downloadTokenArray = [downloadTokens componentsSeparatedByString:@","]; + NSString *bucket = dictionary[kFIRStorageMetadataBucket]; + NSString *path = dictionary[kFIRStorageMetadataName]; + NSString *fullPath = [NSString stringWithFormat:kFIRStorageFullPathFormat, bucket, + [FIRStorageUtils GCSEscapedString:path]]; + + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.scheme = kFIRStorageScheme; + components.host = kFIRStorageHost; + components.percentEncodedPath = fullPath; + + // The backend can return an arbitrary number of download tokens, but we only expose the first + // token via the download URL. + NSURLQueryItem *altItem = [[NSURLQueryItem alloc] initWithName:@"alt" value:@"media"]; + NSURLQueryItem *tokenItem = [[NSURLQueryItem alloc] initWithName:@"token" + value:downloadTokenArray[0]]; + components.queryItems = @[ altItem, tokenItem ]; + + return [components URL]; + } + + return nil; +} + +- (void)enqueue { + __weak FIRStorageGetDownloadURLTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageGetDownloadURLTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidURLError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"GetDownloadURLTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + NSURL *downloadURL; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + downloadURL = + [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:responseDictionary]; + if (!downloadURL) { + self.error = + [FIRStorageErrors errorWithCustomMessage:@"Failed to retrieve a download URL."]; + } + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(downloadURL, self.error); + } + + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +}; + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h new file mode 100644 index 00000000..a4b5ff8f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get a download URL for an object in Firebase Storage. + */ +@interface FIRStorageGetDownloadURLTask () + +/** Extracts a download URL from the StorageMetadata dictonary representation. */ ++ (nullable NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h new file mode 100644 index 00000000..a14c44f0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get metadata on an object in Firebase Storage. + */ +@interface FIRStorageGetMetadataTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidMetadataError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m new file mode 100644 index 00000000..3a947e77 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m @@ -0,0 +1,97 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h" + +#import +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +@implementation FIRStorageGetMetadataTask { + @private + FIRStorageVoidMetadataError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidMetadataError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageGetMetadataTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageGetMetadataTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidMetadataError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"GetMetadataTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(metadata, self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m new file mode 100644 index 00000000..ab887f93 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m @@ -0,0 +1,69 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@implementation FIRStorageListResult + ++ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary *)dictionary + atReference:(FIRStorageReference *)reference { + NSMutableArray *prefixes = [NSMutableArray new]; + NSMutableArray *items = [NSMutableArray new]; + + FIRStorageReference *rootReference = reference.root; + + NSArray *prefixEntries = dictionary[kFIRStorageListPrefixes]; + for (NSString *prefixEntry in prefixEntries) { + NSString *pathWithoutTrailingSlash = prefixEntry; + if ([prefixEntry hasSuffix:@"/"]) { + pathWithoutTrailingSlash = [pathWithoutTrailingSlash substringToIndex:prefixEntry.length - 1]; + } + + FIRStorageReference *prefixReference = [rootReference child:pathWithoutTrailingSlash]; + [prefixes addObject:prefixReference]; + } + + NSArray *> *itemEntries = dictionary[kFIRStorageListItems]; + for (NSDictionary *itemEntry in itemEntries) { + FIRStorageReference *itemReference = [rootReference child:itemEntry[kFIRStorageListItemName]]; + [items addObject:itemReference]; + } + + NSString *pageToken = dictionary[kFIRStorageListPageToken]; + return [[FIRStorageListResult alloc] initWithPrefixes:prefixes items:items pageToken:pageToken]; +} + +- (nullable instancetype)initWithPrefixes:(NSArray *)prefixes + items:(NSArray *)items + pageToken:(nullable NSString *)pageToken { + self = [super init]; + if (self) { + _prefixes = [prefixes copy]; + _items = [items copy]; + _pageToken = [pageToken copy]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageListResult *clone = [[[self class] allocWithZone:zone] initWithPrefixes:_prefixes + items:_items + pageToken:_pageToken]; + + return clone; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h new file mode 100644 index 00000000..f4a2f542 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageListResult (Private) + +/** + * Creates an instance of FIRStorageListResult with the contents of a dictionary. + * + * @param dictionary A dictionary containing the parsed JSON response from the backend. + * @param reference The FIRStorageReference that `list()` was called on. + * @return An instance of FIRStorageListResult that represents the contents of the dictionary. + */ ++ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary *)dictionary + atReference:(FIRStorageReference *)reference; + +/** Initializes a new FIRStorageListResult with the given data. */ +- (nullable instancetype)initWithPrefixes:(NSArray *)prefixes + items:(NSArray *)items + pageToken:(nullable NSString *)pageToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h new file mode 100644 index 00000000..ea3fc48e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h @@ -0,0 +1,57 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Block typedef typically used in `list()` and `listAll()`. + * @param listResult The FIRStorageListResult returned by the operation, if it exists. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidListError)(FIRStorageListResult *_Nullable listResult, + NSError *_Nullable error); + +/** A Task that lists the entries under a {@link StorageReference} */ +@interface FIRStorageListTask : FIRStorageTask + +/** + * Initializes a new List Task. + * + * To schedule the task, invoke `[FIRStorageListTask enqueue]`. + * + * @param reference The location to invoke List on. + * @param service GTMSessionFetcherService to use for the RPC. + * @param queue The queue to schedule the List operation on. + * @param pageSize An optional pageSize, denoting the maximum size of the result set. If + * set to `nil`, the backend will use the default page size. + * @param previousPageToken An optional pageToken, used to resume a previous invocation. + * @param completion The completion handler to be called with the FIRStorageListResult. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + pageSize:(nullable NSNumber *)pageSize + previousPageToken:(nullable NSString *)previousPageToken + completion:(FIRStorageVoidListError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m new file mode 100644 index 00000000..c30bbdc6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m @@ -0,0 +1,127 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageListTask.h" +#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageListTask { + @private + FIRStorageVoidListError _completion; + NSNumber *_pageSize; + NSString *_previousPageToken; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + pageSize:(nullable NSNumber *)pageSize + previousPageToken:(nullable NSString *)previousPageToken + completion:(FIRStorageVoidListError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + _pageSize = pageSize; + _previousPageToken = [previousPageToken copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageListTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageListTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableDictionary *queryParams = [NSMutableDictionary new]; + + NSString *prefix = [self reference].fullPath; + if (prefix.length != 0) { + queryParams[@"prefix"] = [prefix stringByAppendingString:@"/"]; + } + + // Firebase Storage uses file system semantics and treats slashes as separators. GCS's List API + // does not prescribe a separator, and hence we need to provide a slash as the delimiter. + queryParams[@"delimiter"] = @"/"; + + // listAll() doesn't set a pageSize as this allows Firebase Storage to determine how many items + // to return per page. This removes the need to backfill results if Firebase Storage filters + // objects that are considered invalid (such as items with two consecutive slashes). + if (strongSelf->_pageSize != nil) { + queryParams[@"maxResults"] = [strongSelf->_pageSize stringValue]; + } + + if (strongSelf->_previousPageToken) { + queryParams[@"pageToken"] = strongSelf->_previousPageToken; + } + + FIRStoragePath *basePath = [[FIRStoragePath alloc] initWithBucket:self.reference.bucket + object:nil]; + NSMutableURLRequest *request = + [[FIRStorageUtils defaultRequestForPath:basePath queryParams:queryParams] mutableCopy]; + + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidListError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"ListTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageListResult *listResult; + if (error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + listResult = [FIRStorageListResult fromDictionary:responseDictionary + atReference:self.reference]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(listResult, self.error); + } + + // Remove retain cycle set up by `strongSelf->_fetcherCompletion` + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m new file mode 100644 index 00000000..c6921295 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m @@ -0,0 +1,224 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +// TODO: consider rewriting this using GTLR (GTLRStorageObjects.h) +@implementation FIRStorageMetadata + +#pragma mark - Initializers + +- (instancetype)init { + return [self initWithDictionary:[NSDictionary dictionary]]; +} + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _initialMetadata = [dictionary copy]; + + _bucket = dictionary[kFIRStorageMetadataBucket]; + _cacheControl = dictionary[kFIRStorageMetadataCacheControl]; + _contentDisposition = dictionary[kFIRStorageMetadataContentDisposition]; + _contentEncoding = dictionary[kFIRStorageMetadataContentEncoding]; + _contentLanguage = dictionary[kFIRStorageMetadataContentLanguage]; + _contentType = dictionary[kFIRStorageMetadataContentType]; + _customMetadata = dictionary[kFIRStorageMetadataCustomMetadata]; + _size = [dictionary[kFIRStorageMetadataSize] longLongValue]; + _generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue]; + _metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue]; + _timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]]; + _updated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataUpdated]]; + _md5Hash = dictionary[kFIRStorageMetadataMd5Hash]; + // GCS "name" is our path, our "name" is just the last path component of the path + _path = dictionary[kFIRStorageMetadataName]; + _name = [_path lastPathComponent]; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageMetadata *clone = + [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]]; + clone.initialMetadata = [self.initialMetadata copy]; + return clone; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorageMetadata class]]) { + return NO; + } + + BOOL isEqualObject = [self isEqualToFIRStorageMetadata:(FIRStorageMetadata *)object]; + return isEqualObject; +} + +- (BOOL)isEqualToFIRStorageMetadata:(FIRStorageMetadata *)metadata { + return [[self dictionaryRepresentation] isEqualToDictionary:[metadata dictionaryRepresentation]]; +} + +- (NSUInteger)hash { + NSUInteger hash = [[self dictionaryRepresentation] hash]; + return hash; +} + +- (NSString *)description { + NSDictionary *metadataDictionary = [self dictionaryRepresentation]; + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, metadataDictionary]; +} + +#pragma mark - Public methods + +- (NSDictionary *)dictionaryRepresentation { + NSMutableDictionary *metadataDictionary = [[NSMutableDictionary alloc] initWithCapacity:13]; + + if (_bucket) { + metadataDictionary[kFIRStorageMetadataBucket] = _bucket; + } + + if (_cacheControl) { + metadataDictionary[kFIRStorageMetadataCacheControl] = _cacheControl; + } + + if (_contentDisposition) { + metadataDictionary[kFIRStorageMetadataContentDisposition] = _contentDisposition; + } + + if (_contentEncoding) { + metadataDictionary[kFIRStorageMetadataContentEncoding] = _contentEncoding; + } + + if (_contentLanguage) { + metadataDictionary[kFIRStorageMetadataContentLanguage] = _contentLanguage; + } + + if (_contentType) { + metadataDictionary[kFIRStorageMetadataContentType] = _contentType; + } + + if (_md5Hash) { + metadataDictionary[kFIRStorageMetadataMd5Hash] = _md5Hash; + } + + if (_customMetadata) { + metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata; + } + + if (_generation) { + NSString *generationString = [NSString stringWithFormat:@"%lld", _generation]; + metadataDictionary[kFIRStorageMetadataGeneration] = generationString; + } + + if (_metageneration) { + NSString *metagenerationString = [NSString stringWithFormat:@"%lld", _metageneration]; + metadataDictionary[kFIRStorageMetadataMetageneration] = metagenerationString; + } + + if (_timeCreated) { + metadataDictionary[kFIRStorageMetadataTimeCreated] = [self RFC3339StringFromDate:_timeCreated]; + } + + if (_updated) { + metadataDictionary[kFIRStorageMetadataUpdated] = [self RFC3339StringFromDate:_updated]; + } + + if (_path) { + metadataDictionary[kFIRStorageMetadataName] = _path; + } + + if (_size) { + metadataDictionary[kFIRStorageMetadataSize] = [NSNumber numberWithLongLong:_size]; + } + + return [metadataDictionary copy]; +} + +- (BOOL)isFile { + return _type == FIRStorageMetadataTypeFile; +} + +- (BOOL)isFolder { + return _type == FIRStorageMetadataTypeFolder; +} + +#pragma mark - Private methods + ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata { + for (NSString *metadataKey in [oldMetadata allKeys]) { + id oldValue = [oldMetadata objectForKey:metadataKey]; + id newValue = [metadata objectForKey:metadataKey]; + + if (oldValue && !newValue) { + [metadata setObject:[NSNull null] forKey:metadataKey]; + } else if ([oldValue isKindOfClass:[NSString class]] && + [newValue isKindOfClass:[NSString class]]) { + if ([oldValue isEqualToString:newValue]) { + [metadata removeObjectForKey:metadataKey]; + } + } else if ([oldValue isKindOfClass:[NSDictionary class]] && + [newValue isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *nestedMetadata = [newValue mutableCopy]; + [self removeMatchingMetadata:nestedMetadata oldMetadata:oldValue]; + [metadata setObject:[nestedMetadata copy] forKey:metadataKey]; + } + } +} + +- (NSDictionary *)updatedMetadata { + NSMutableDictionary *metadataUpdate = [[self dictionaryRepresentation] mutableCopy]; + [FIRStorageMetadata removeMatchingMetadata:metadataUpdate oldMetadata:_initialMetadata]; + return [metadataUpdate copy]; +} + +#pragma mark - RFC 3339 conversions + +static NSDateFormatter *sRFC3339DateFormatter; + +static void setupDateFormatterOnce(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRFC3339DateFormatter = [[NSDateFormatter alloc] init]; + NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + + [sRFC3339DateFormatter setLocale:enUSPOSIXLocale]; + [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZZZ"]; + [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; + }); +} + +- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString { + setupDateFormatterOnce(); + NSDate *rfc3339Date = [sRFC3339DateFormatter dateFromString:dateString]; + return rfc3339Date; +} + +- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date { + setupDateFormatterOnce(); + NSString *rfc3339String = [sRFC3339DateFormatter stringFromDate:date]; + return rfc3339String; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h new file mode 100644 index 00000000..30faa267 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageMetadata () + +@property(readwrite, nonatomic) NSString *name; + +@property(readwrite, nonatomic) NSString *path; + +@property(readwrite, nonatomic) FIRStorageReference *reference; + +/** + * The type of the object, either a "File" or a "Folder". + */ +@property(readwrite) FIRStorageMetadataType type; + +/** + * The original metadata representation received from the server or an empty dictionary + * if the metadata object was initialized by the user. + */ +@property(copy, nonatomic) NSDictionary *initialMetadata; + +/** + * Recursively removes entries in 'metadata' that are unmodified from 'oldMetadata'. + * Adds 'NSNull' for entries that only exist in oldMetadata. + */ ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata; + +/** + * Computes the updates between the state at initialization and the current state. + * Returns a dictionary with only the updated data. Removed keys are set to NSNull. + */ +- (NSDictionary *)updatedMetadata; + +/** + * Returns an RFC3339 formatted date from a string. + * @param dateString An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ. + * @return An NSDate populated from the string or nil if conversion isn't possible. + */ +- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString; + +/** + * Returns an RFC3339 formatted string from an NSDate object. + * @param date The NSDate object to be converted to a string. + * @return An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ or nil if conversion isn't possible. + */ +- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m new file mode 100644 index 00000000..858138e7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m @@ -0,0 +1,215 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageObservableTask { + @private + // Handlers for pause, resume, progress, success, and failure callbacks + NSMutableDictionary *_resumeHandlers; + NSMutableDictionary *_pauseHandlers; + NSMutableDictionary *_progressHandlers; + NSMutableDictionary *_successHandlers; + NSMutableDictionary *_failureHandlers; + // Reverse map of fetcher handles to status types + NSMutableDictionary *_handleToStatusMap; +} + +@synthesize state = _state; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _pauseHandlers = [[NSMutableDictionary alloc] init]; + _resumeHandlers = [[NSMutableDictionary alloc] init]; + _progressHandlers = [[NSMutableDictionary alloc] init]; + _successHandlers = [[NSMutableDictionary alloc] init]; + _failureHandlers = [[NSMutableDictionary alloc] init]; + _handleToStatusMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +#pragma mark - Observers + +- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status + handler:(FIRStorageVoidSnapshot)handler { + FIRStorageVoidSnapshot callback = handler; + + // Note: self.snapshot is synchronized + FIRStorageTaskSnapshot *snapshot = self.snapshot; + // TODO: use an increasing counter instead of a random UUID + NSString *UUIDString = [[NSUUID UUID] UUIDString]; + switch (status) { + case FIRStorageTaskStatusPause: + @synchronized(self) { + [_pauseHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStatePausing || _state == FIRStorageTaskStatePaused) { + [self fireHandlers:_pauseHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusResume: + @synchronized(self) { + [_resumeHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateResuming || _state == FIRStorageTaskStateRunning) { + [self fireHandlers:_resumeHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusProgress: + @synchronized(self) { + [_progressHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateRunning || _state == FIRStorageTaskStateProgress) { + [self fireHandlers:_progressHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusSuccess: + @synchronized(self) { + [_successHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateSuccess) { + [self fireHandlers:_successHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusFailure: + @synchronized(self) { + [_failureHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateFailing || _state == FIRStorageTaskStateFailed) { + [self fireHandlers:_failureHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusUnknown: + // Fall through to exception case if an unknown status is passed + + default: + [NSException raise:NSInternalInconsistencyException + format:kFIRStorageInvalidObserverStatus, nil]; + break; + } + + @synchronized(self) { + _handleToStatusMap[UUIDString] = @(status); + } // @synchronized(self) + + return UUIDString; +} + +- (void)removeObserverWithHandle:(FIRStorageHandle)handle { + FIRStorageTaskStatus status = [_handleToStatusMap[handle] intValue]; + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + + @synchronized(self) { + [observerDictionary removeObjectForKey:handle]; + [_handleToStatusMap removeObjectForKey:handle]; + } // @synchronized(self) +} + +- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status { + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + [self removeHandlersFromStatusMapForDictionary:observerDictionary]; + + @synchronized(self) { + [observerDictionary removeAllObjects]; + } // @synchronized(self) +} + +- (void)removeAllObservers { + @synchronized(self) { + [_pauseHandlers removeAllObjects]; + [_resumeHandlers removeAllObjects]; + [_progressHandlers removeAllObjects]; + [_successHandlers removeAllObjects]; + [_failureHandlers removeAllObjects]; + [_handleToStatusMap removeAllObjects]; + } // @synchronized(self) +} + +- (NSMutableDictionary *)handlerDictionaryForStatus: + (FIRStorageTaskStatus)status { + switch (status) { + case FIRStorageTaskStatusPause: + return _pauseHandlers; + + case FIRStorageTaskStatusResume: + return _resumeHandlers; + + case FIRStorageTaskStatusProgress: + return _progressHandlers; + + case FIRStorageTaskStatusSuccess: + return _successHandlers; + + case FIRStorageTaskStatusFailure: + return _failureHandlers; + + case FIRStorageTaskStatusUnknown: + return [NSMutableDictionary dictionary]; + + default: + [NSException raise:NSInternalInconsistencyException + format:kFIRStorageInvalidObserverStatus, nil]; + return nil; + } +} + +- (void)removeHandlersFromStatusMapForDictionary: + (NSMutableDictionary *)dict { + @synchronized(self) { + [_handleToStatusMap removeObjectsForKeys:dict.allKeys]; + } // @synchronized(self) +} + +- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot { + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + [self fireHandlers:observerDictionary snapshot:snapshot]; +} + +- (void)fireHandlers:(NSMutableDictionary *)handlers + snapshot:(FIRStorageTaskSnapshot *)snapshot { + dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + // TODO: iterate over this list in a consistent order + NSMutableDictionary *handlersCopy; + @synchronized(self) { + handlersCopy = [handlers copy]; + } // @synchronized(self) + [handlersCopy + enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull key, FIRStorageVoidSnapshot _Nonnull handler, BOOL *_Nonnull stop) { + dispatch_async(callbackQueue, ^{ + handler(snapshot); + }); + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h new file mode 100644 index 00000000..fb8081d9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; +@class FIRStorageTaskSnapshot; +@class GTMSessionFetcherService; + +@interface FIRStorageObservableTask () + +/** + * Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService. + * @param reference A FIRStorageReference the task will be performed on. + * @param service A GTMSessionFetcherService which provides the fetchers and configuration for + * requests. + * @param queue The shared queue to use for all Storage operations. + * @return A new FIRStorageTask representing the current task. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue; + +/** + * Raise events for a given task status by passing along a snapshot of existing task state. + * @param status A FIRStorageTaskStatus to raise events for. + * @param snapshot A FIRStorageTaskSnapshot snapshot of task state to pass through the handler. + */ +- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h new file mode 100644 index 00000000..53ff7ef8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h @@ -0,0 +1,106 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents a path in GCS, which can be represented as: gs://bucket/path/to/object + * or http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object?token=<12345> + * This class also includes helper methods to parse those URI/Ls, as well as to + * add and remove path segments. + */ +@interface FIRStoragePath : NSObject + +/** + * The GCS bucket in the path. + */ +@property(copy, nonatomic) NSString *bucket; + +/** + * The GCS object in the path. + */ +@property(copy, nonatomic, nullable) NSString *object; + +/** + * Parses a generic string (representing some URI or URL) and returns the appropriate path. + * @param string String which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid gs:// URI or http[s]:// URL. + */ ++ (nullable FIRStoragePath *)pathFromString:(NSString *)string; + +/** + * Parses a gs://bucket/path/to/object URI into a GCS path. + * @param aURIString gs:// URI which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid gs:// URI. + */ ++ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString; + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Constructs an FIRStoragePath object that represents the given bucket and object. + * @param bucket The name of the bucket. + * @param object The name of the object. + * @return An instance of FIRStoragePath representing the @a bucket and @a object. + */ +- (instancetype)initWithBucket:(NSString *)bucket + object:(nullable NSString *)object NS_DESIGNATED_INITIALIZER; + +/** + * Parses a http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object...?token=<12345> + * URL into a GCS path. + * @param aURLString http[s]:// URL which is parsed into a path. + * string which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid http[s]:// URL. + */ ++ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString; + +/** + * Creates a new path based off of the current path and a string appended to it. + * Note that all slashes are compressed to a single slash, and leading and trailing slashes + * are removed. + * @param path String to append to the current path. + * @return Returns a new instance of FIRStoragePath with the new path appended. + */ +- (FIRStoragePath *)child:(NSString *)path; + +/** + * Creates a new path based off of the current path with the last path segment removed. + * @return Returns a new instance of FIRStoragePath pointing to the parent path, + * or nil if the current path points to the root. + */ +- (nullable FIRStoragePath *)parent; + +/** + * Creates a new path based off of the root of the bucket. + * @return Returns a new instance of FIRStoragePath pointing to the root of the bucket. + */ +- (FIRStoragePath *)root; + +/** + * Returns a GS URI representing the current path. + * @return Returns a gs://bucket/path/to/object URI representing the current path. + */ +- (NSString *)stringValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m new file mode 100644 index 00000000..ef897d8b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m @@ -0,0 +1,199 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@implementation FIRStoragePath + +#pragma mark - Class methods + ++ (nullable FIRStoragePath *)pathFromString:(NSString *)string { + if ([string hasPrefix:@"gs://"]) { + // "gs://bucket/path/to/object" + return [FIRStoragePath pathFromGSURI:string]; + } else if ([string hasPrefix:@"http://"] || [string hasPrefix:@"https://"]) { + // "http[s]://firebasestorage.googleapis.com/bucket/path/to/object?signed_url_params" + return [FIRStoragePath pathFromHTTPURL:string]; + } else { + // Invalid scheme, raise an exception! + [NSException raise:NSInternalInconsistencyException + format:@"URL scheme must be one of gs://, http://, or https:// "]; + return nil; + } +} + ++ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString { + NSString *bucketName; + NSString *objectName; + NSScanner *scanner = [NSScanner scannerWithString:aURIString]; + BOOL isGSURI = [scanner scanString:@"gs://" intoString:NULL]; + BOOL hasBucket = [scanner scanUpToString:@"/" intoString:&bucketName]; + [scanner scanString:@"/" intoString:NULL]; + [scanner scanUpToString:@"\n" intoString:&objectName]; + + if (!isGSURI || !hasBucket) { + [NSException raise:NSInternalInconsistencyException + format:@"URI must be in the form of gs:///"]; + return nil; + } + + return [[self alloc] initWithBucket:bucketName object:objectName]; +} + ++ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString { + NSString *bucketName; + NSString *objectName; + NSURL *httpsURL = [NSURL URLWithString:aURLString]; + NSArray *pathComponents = httpsURL.pathComponents; // [/, v0, b, , o, ] + + if ([httpsURL.host isEqual:kFIRStorageHost]) { + // Have a bucket name + if ([pathComponents count] > 3) { + bucketName = pathComponents[3]; + } + + // Have an object name + if ([pathComponents count] > 5) { + NSRange objectRange = NSMakeRange(5, [pathComponents count] - 5); + objectName = [[pathComponents subarrayWithRange:objectRange] componentsJoinedByString:@"/"]; + } + } + + if (bucketName.length == 0) { + [NSException raise:NSInternalInconsistencyException + format:@"URL must be in the form of " + @"http[s]://firebasestorage.googleapis.com/v0/b//o/[?token=signed_url_params]"]; + return nil; + } + + if (objectName.length == 0) { + objectName = nil; + } + + return [[self alloc] initWithBucket:bucketName object:objectName]; +} + +#pragma mark - Initializers + +- (instancetype)initWithBucket:(NSString *)bucket object:(nullable NSString *)object { + self = [super init]; + if (self) { + _bucket = [bucket copy]; + _object = [self standardizedPathForString:[object copy]]; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithBucket:_bucket object:_object]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStoragePath class]]) { + return NO; + } + + BOOL isObjectEqual = [self isEqualToFIRStoragePath:(FIRStoragePath *)object]; + return isObjectEqual; +} + +- (BOOL)isEqualToFIRStoragePath:(FIRStoragePath *)path { + BOOL isBucketEqual = _bucket == nil && path->_bucket == nil; + BOOL isObjectEqual = _object == nil && path->_object == nil; + + if (_bucket && path->_bucket) { + isBucketEqual = [_bucket isEqual:path->_bucket]; + } + + if (_object && path.object) { + isObjectEqual = [_object isEqual:path->_object]; + } + + BOOL isEqual = isBucketEqual && isObjectEqual; + return isEqual; +} + +- (NSUInteger)hash { + // "...because in those days, you could XOR anything with anything and get something useful..." + // https://www.usenix.org/system/files/1309_14-17_mickens.pdf + NSUInteger hash = [_bucket hash] ^ [_object hash]; + return hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, [self stringValue]]; +} + +- (NSString *)stringValue { + return [NSString stringWithFormat:@"gs://%@/%@", _bucket, _object ?: @""]; +} + +#pragma mark - Public methods + +- (FIRStoragePath *)child:(NSString *)path { + if (path.length == 0) { + return [self copy]; // Return a copy of the same path, nothing happened + } + + NSString *childObject; + if (_object == nil) { + childObject = path; + } else { + childObject = [_object stringByAppendingPathComponent:path]; + } + + FIRStoragePath *childPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:childObject]; + return childPath; +} + +- (nullable FIRStoragePath *)parent { + if (_object.length == 0) { + return nil; + } + + NSString *parentObject = [_object stringByDeletingLastPathComponent]; + FIRStoragePath *parentPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:parentObject]; + return parentPath; +} + +- (FIRStoragePath *)root { + FIRStoragePath *rootPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:nil]; + return rootPath; +} + +#pragma mark - Private methods + +// Removes leading and trailing slashes, and compresses multiple slashes +// to create a canonical representation. +// Example: /foo//bar///baz//// -> foo/bar/baz +- (NSString *)standardizedPathForString:(NSString *)string { + NSMutableArray *components = [[string componentsSeparatedByString:@"/"] mutableCopy]; + NSIndexSet *removedPaths = + [components indexesOfObjectsPassingTest:^BOOL(NSString *string, NSUInteger idx, BOOL *stop) { + return (string.length == 0); + }]; + [components removeObjectsAtIndexes:removedPaths]; + return [components componentsJoinedByString:@"/"]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m new file mode 100644 index 00000000..cf687b4f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m @@ -0,0 +1,487 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageDeleteTask.h" +#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" +#import "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h" +#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h" +#import "FirebaseStorage/Sources/FIRStorageListTask.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h" +#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import +#import + +@implementation FIRStorageReference + +- (instancetype)init { + FIRStorage *storage = [FIRStorage storage]; + NSString *storageBucket = storage.app.options.storageBucket; + FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:storageBucket object:nil]; + FIRStorageReference *reference = [self initWithStorage:storage path:path]; + return reference; +} + +- (instancetype)initWithStorage:(FIRStorage *)storage path:(FIRStoragePath *)path { + self = [super init]; + if (self) { + _storage = storage; + _path = path; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageReference *copiedReference = [[[self class] allocWithZone:zone] initWithStorage:_storage + path:_path]; + return copiedReference; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorageReference class]]) { + return NO; + } + + BOOL isObjectEqual = [self isEqualToFIRStorageReference:(FIRStorageReference *)object]; + return isObjectEqual; +} + +- (BOOL)isEqualToFIRStorageReference:(FIRStorageReference *)reference { + BOOL isEqual = [_storage isEqual:reference.storage] && [_path isEqual:reference.path]; + return isEqual; +} + +- (NSUInteger)hash { + NSUInteger hash = [_storage hash] ^ [_path hash]; + return hash; +} + +- (NSString *)description { + return [self stringValue]; +} + +- (NSString *)stringValue { + NSString *value = [NSString stringWithFormat:@"gs://%@/%@", _path.bucket, _path.object ?: @""]; + return value; +} + +#pragma mark - Property Getters + +- (NSString *)bucket { + NSString *bucket = _path.bucket; + return bucket; +} + +- (NSString *)fullPath { + NSString *path = _path.object; + if (!path) { + path = @""; + } + return path; +} + +- (NSString *)name { + NSString *name = [_path.object lastPathComponent]; + if (!name) { + name = @""; + } + return name; +} + +#pragma mark - Path Operations + +- (FIRStorageReference *)root { + FIRStoragePath *rootPath = [_path root]; + FIRStorageReference *rootReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:rootPath]; + return rootReference; +} + +- (nullable FIRStorageReference *)parent { + FIRStoragePath *parentPath = [_path parent]; + if (!parentPath) { + return nil; + } + + FIRStorageReference *parentReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:parentPath]; + return parentReference; +} + +- (FIRStorageReference *)child:(NSString *)path { + FIRStoragePath *childPath = [_path child:path]; + FIRStorageReference *childReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:childPath]; + return childReference; +} + +#pragma mark - Uploads + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData { + return [self putData:uploadData metadata:nil completion:nil]; +} + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata { + return [self putData:uploadData metadata:metadata completion:nil]; +} + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + if (!metadata) { + metadata = [[FIRStorageMetadata alloc] init]; + } + + metadata.path = _path.object; + metadata.name = [_path.object lastPathComponent]; + FIRStorageUploadTask *task = + [[FIRStorageUploadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + data:uploadData + metadata:metadata]; + + if (completion) { + __block BOOL completed = NO; + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(snapshot.metadata, nil); + } + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(nil, snapshot.error); + } + }); + }]; + } + [task enqueue]; + return task; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL { + return [self putFile:fileURL metadata:nil completion:nil]; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata { + return [self putFile:fileURL metadata:metadata completion:nil]; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + if (!metadata) { + metadata = [[FIRStorageMetadata alloc] init]; + } + + metadata.path = _path.object; + metadata.name = [_path.object lastPathComponent]; + FIRStorageUploadTask *task = + [[FIRStorageUploadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:fileURL + metadata:metadata]; + + if (completion) { + __block BOOL completed = NO; + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(snapshot.metadata, nil); + } + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(nil, snapshot.error); + } + }); + }]; + } + [task enqueue]; + return task; +} + +#pragma mark - Downloads + +- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size + completion:(FIRStorageVoidDataError)completion { + __block BOOL completed = NO; + FIRStorageDownloadTask *task = + [[FIRStorageDownloadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:nil]; + + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + FIRStorageDownloadTask *task = snapshot.task; + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(task.downloadData, nil); + } + }); + }]; + + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(nil, snapshot.error); + } + }); + }]; + [task + observeStatus:FIRStorageTaskStatusProgress + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + FIRStorageDownloadTask *task = snapshot.task; + if (task.progress.totalUnitCount > size || task.progress.completedUnitCount > size) { + NSDictionary *infoDictionary = + @{@"totalSize" : @(task.progress.totalUnitCount), + @"maxAllowedSize" : @(size)}; + NSError *error = + [FIRStorageErrors errorWithCode:FIRStorageErrorCodeDownloadSizeExceeded + infoDictionary:infoDictionary]; + [task cancelWithError:error]; + } + }]; + [task enqueue]; + return task; +} + +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL { + return [self writeToFile:fileURL completion:nil]; +} + +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL + completion:(FIRStorageVoidURLError)completion { + FIRStorageDownloadTask *task = + [[FIRStorageDownloadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:fileURL]; + if (completion) { + __block BOOL completed = NO; + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(fileURL, nil); + } + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + if (!completed) { + completed = YES; + completion(nil, snapshot.error); + } + }); + }]; + } + [task enqueue]; + return task; +} + +- (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion { + FIRStorageGetDownloadURLTask *task = + [[FIRStorageGetDownloadURLTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +#pragma mark - List + +- (void)listWithMaxResults:(int64_t)maxResults completion:(FIRStorageVoidListError)completion { + if (maxResults <= 0 || maxResults > 1000) { + completion(nil, + [FIRStorageUtils storageErrorWithDescription: + @"Argument 'maxResults' must be between 1 and 1000 inclusive." + code:FIRStorageErrorCodeInvalidArgument]); + } else { + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:@(maxResults) + previousPageToken:nil + completion:completion]; + [task enqueue]; + } +} + +- (void)listWithMaxResults:(int64_t)maxResults + pageToken:(NSString *)pageToken + completion:(FIRStorageVoidListError)completion { + if (maxResults <= 0 || maxResults > 1000) { + completion(nil, + [FIRStorageUtils storageErrorWithDescription: + @"Argument 'maxResults' must be between 1 and 1000 inclusive." + code:FIRStorageErrorCodeInvalidArgument]); + } else { + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:@(maxResults) + previousPageToken:pageToken + completion:completion]; + [task enqueue]; + } +} + +- (void)listAllWithCompletion:(FIRStorageVoidListError)completion { + NSMutableArray *prefixes = [NSMutableArray new]; + NSMutableArray *items = [NSMutableArray new]; + + __weak FIRStorageReference *weakSelf = self; + + __block FIRStorageVoidListError paginatedCompletion = + ^(FIRStorageListResult *listResult, NSError *error) { + if (error) { + completion(nil, error); + } + + FIRStorageReference *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + + [prefixes addObjectsFromArray:listResult.prefixes]; + [items addObjectsFromArray:listResult.items]; + + if (listResult.pageToken) { + FIRStorageListTask *nextPage = [[FIRStorageListTask alloc] + initWithReference:self + fetcherService:strongSelf->_storage.fetcherServiceForApp + dispatchQueue:strongSelf->_storage.dispatchQueue + pageSize:nil + previousPageToken:listResult.pageToken + completion:paginatedCompletion]; + [nextPage enqueue]; + } else { + FIRStorageListResult *result = [[FIRStorageListResult alloc] initWithPrefixes:prefixes + items:items + pageToken:nil]; + // Break the retain cycle we set up indirectly by passing the callback to `nextPage`. + paginatedCompletion = nil; + completion(result, nil); + } + }; + + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:nil + previousPageToken:nil + completion:paginatedCompletion]; + + [task enqueue]; +} + +#pragma mark - Metadata Operations + +- (void)metadataWithCompletion:(FIRStorageVoidMetadataError)completion { + FIRStorageGetMetadataTask *task = + [[FIRStorageGetMetadataTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +- (void)updateMetadata:(FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + FIRStorageUpdateMetadataTask *task = + [[FIRStorageUpdateMetadataTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + metadata:metadata + completion:completion]; + [task enqueue]; +} + +#pragma mark - Delete + +- (void)deleteWithCompletion:(nullable FIRStorageVoidError)completion { + FIRStorageDeleteTask *task = + [[FIRStorageDeleteTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h new file mode 100644 index 00000000..84a36b52 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageReference () + +@property(nonatomic, readwrite) FIRStorage *storage; + +/** + * The current path which points to an object in the Google Cloud Storage bucket. + */ +@property(strong, nonatomic) FIRStoragePath *path; + +- (instancetype)initWithStorage:(FIRStorage *)storage + path:(FIRStoragePath *)path NS_DESIGNATED_INITIALIZER; + +- (NSString *)stringValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m new file mode 100644 index 00000000..49bc109a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m @@ -0,0 +1,68 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import +#import +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import + +@implementation FIRStorageTask + +- (instancetype)init { + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." + reason:@"init unavailable, use designated initializer" + userInfo:nil]; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue { + self = [super init]; + if (self) { + _reference = reference; + _baseRequest = [FIRStorageUtils defaultRequestForPath:reference.path]; + _fetcherService = service; + _fetcherService.maxRetryInterval = _reference.storage.maxOperationRetryTime; + _dispatchQueue = queue; + } + return self; +} + +- (FIRStorageTaskSnapshot *)snapshot { + @synchronized(self) { + NSProgress *progress = [NSProgress progressWithTotalUnitCount:self.progress.totalUnitCount]; + progress.completedUnitCount = self.progress.completedUnitCount; + FIRStorageTaskSnapshot *snapshot = + [[FIRStorageTaskSnapshot alloc] initWithTask:self + state:self.state + metadata:self.metadata + reference:self.reference + progress:progress + error:[self.error copy]]; + return snapshot; + } +} + +- (void)dispatchAsync:(void (^)(void))block { + dispatch_async(self.dispatchQueue, block); +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m new file mode 100644 index 00000000..c5f7c2b3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m @@ -0,0 +1,87 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageTaskSnapshot + +- (instancetype)initWithTask:(__kindof FIRStorageTask *)task + state:(FIRStorageTaskState)state + metadata:(nullable FIRStorageMetadata *)metadata + reference:(FIRStorageReference *)reference + progress:(nullable NSProgress *)progress + error:(nullable NSError *)error { + self = [super init]; + if (self) { + _task = task; + _metadata = metadata; + _reference = reference; + _progress = progress; + _error = error; + + switch (state) { + case FIRStorageTaskStateQueueing: + case FIRStorageTaskStateRunning: + case FIRStorageTaskStateResuming: + _status = FIRStorageTaskStatusResume; + break; + + case FIRStorageTaskStateProgress: + _status = FIRStorageTaskStatusProgress; + break; + + case FIRStorageTaskStatePaused: + case FIRStorageTaskStatePausing: + _status = FIRStorageTaskStatusPause; + break; + + case FIRStorageTaskStateSuccess: + case FIRStorageTaskStateCompleting: + _status = FIRStorageTaskStatusSuccess; + break; + + case FIRStorageTaskStateCancelled: + case FIRStorageTaskStateFailing: + case FIRStorageTaskStateFailed: + _status = FIRStorageTaskStatusFailure; + break; + + default: + _status = FIRStorageTaskStatusUnknown; + } + } + return self; +} + +- (NSString *)description { + switch (_status) { + case FIRStorageTaskStatusResume: + return @""; + case FIRStorageTaskStatusProgress: + return [NSString stringWithFormat:@"", _progress]; + case FIRStorageTaskStatusPause: + return @""; + case FIRStorageTaskStatusSuccess: + return @""; + case FIRStorageTaskStatusFailure: + return [NSString stringWithFormat:@"", _error]; + default: + return @""; + }; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h new file mode 100644 index 00000000..4ffc9712 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageMetadata; +@class FIRStorageReference; +@class FIRStorageTask; + +@interface FIRStorageTaskSnapshot () + +@property(readwrite, copy, nonatomic) FIRStorageTask *task; +@property(readwrite, copy, nonatomic) FIRStorageMetadata *metadata; +@property(readwrite, copy, nonatomic) FIRStorageReference *reference; +@property(readwrite, strong, nonatomic) NSProgress *progress; +@property(readwrite, copy, nonatomic) NSError *error; + +/** + * Creates a new task snapshot from the given properties. + * @param task The task being represented in this snapshot. + * @param state The current state of the parent task. + * @param metadata The FIRStorageMetadata of a task. Before upload/update, contains the metadata + * to be updated; after, contains the returned metadata. May be nil if no metadata is provided + * or returned. + * @param reference The FIRStorageReference that spawned the task this snapshot is based on. + * @param progress An NSProgress object containing progress of the task this snapshot is based on, + * or nil if the task doesn't report progress. + * @param error An NSError object containing an error that occurred during the task, + * if one occurred. + * @return Returns the constructed snapshot. + */ +- (instancetype)initWithTask:(__kindof FIRStorageTask *)task + state:(FIRStorageTaskState)state + metadata:(nullable FIRStorageMetadata *)metadata + reference:(FIRStorageReference *)reference + progress:(nullable NSProgress *)progress + error:(nullable NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h new file mode 100644 index 00000000..6d441e70 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageTask () + +/** + * State for the current task in progress. + */ +@property(atomic) FIRStorageTaskState state; + +/** + * FIRStorageMetadata for the task in progress, or nil if none present. + */ +@property(strong, nonatomic, nullable) FIRStorageMetadata *metadata; + +/** + * Error which occurred during task execution, or nil if no error occurred. + */ +@property(strong, nonatomic, nullable) NSError *error; + +/** + * NSProgress object which tracks the progess of an observable task. + */ +@property(strong, nonatomic) NSProgress *progress; + +/** + * Reference pointing to the location the task is being performed against. + */ +@property(strong, nonatomic) FIRStorageReference *reference; + +/** + * A serial queue for all storage operations. + */ +@property(nonatomic, readonly) dispatch_queue_t dispatchQueue; + +@property(strong, readwrite, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot; + +@property(readonly, copy, nonatomic) NSURLRequest *baseRequest; + +@property(strong, atomic) GTMSessionFetcher *fetcher; + +@property(readonly, nonatomic) GTMSessionFetcherService *fetcherService; + +@property(readonly, copy) GTMSessionFetcherCompletionHandler fetcherCompletion; + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService. + * @param reference A FIRStorageReference the task will be performed on. + * @param service A GTMSessionFetcherService which provides the fetchers and configuration for + * requests. + * @param queue The shared queue to use for all Storage operations. + * @return A new FIRStorageTask representing the current task. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER; + +/** Dispatches a block on the shared Storage queue. */ +- (void)dispatchAsync:(void (^)(void))block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h new file mode 100644 index 00000000..75893dd0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FIRAuthInterop; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper class for FIRAuthInterop that implements the GTMFetcherAuthorizationProtocol, + * so as to easily provide GTMSessionFetcher fetches a Firebase Authentication JWT + * for the current logged in user. Handles token expiration and other failure cases. + * If no authentication provider exists or no token is found, no token is added + * and the request is passed. + */ +@interface FIRStorageTokenAuthorizer : NSObject + +/** + * Initializes the token authorizer with an instance of FIRApp. + * @param googleAppID The Google AppID of the app to send with the request. + * @param auth An instance that provides access to Auth functionality, if it exists. + * @return Returns an instance of FIRStorageTokenAuthorizer which adds the appropriate + * "Authorization" header to all outbound requests. Note that a token may not be added + * if the Auth instance is nil. This allows for unauthenticated access, if Firebase + * Storage rules allow for it. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + fetcherService:(GTMSessionFetcherService *)service + authProvider:(nullable id)auth; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m new file mode 100644 index 00000000..79b50162 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m @@ -0,0 +1,132 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h" + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" + +#import "Interop/Auth/Public/FIRAuthInterop.h" + +@implementation FIRStorageTokenAuthorizer { + @private + /// Google App ID to pass along with each request. + NSString *_googleAppID; + + /// Auth provider. + id _auth; +} + +@synthesize fetcherService = _fetcherService; + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + fetcherService:(GTMSessionFetcherService *)service + authProvider:(nullable id)auth { + self = [super init]; + if (self) { + _googleAppID = googleAppID; + _fetcherService = service; + _auth = auth; + } + return self; +} + +#pragma mark - GTMFetcherAuthorizationProtocol methods + +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel { + // Set version header on each request + NSString *versionString = [NSString stringWithFormat:@"ios/%s", FIRStorageVersionString]; + [request setValue:versionString forHTTPHeaderField:@"x-firebase-storage-version"]; + + // Set GMP ID on each request + [request setValue:_googleAppID forHTTPHeaderField:@"x-firebase-gmpid"]; + + if (delegate && sel) { + id selfParam = self; + NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate]; + [invocation setArgument:&selfParam atIndex:2]; + [invocation setArgument:&request atIndex:3]; + + dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [invocation retainArguments]; + if (_auth) { + [_auth getTokenForcingRefresh:NO + withCallback:^(NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + NSMutableDictionary *errorDictionary = + [NSMutableDictionary dictionaryWithDictionary:error.userInfo]; + errorDictionary[kFIRStorageResponseErrorDomain] = error.domain; + errorDictionary[kFIRStorageResponseErrorCode] = @(error.code); + + NSError *tokenError = + [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnauthenticated + infoDictionary:errorDictionary]; + [invocation setArgument:&tokenError atIndex:4]; + } else if (token) { + NSString *firebaseToken = + [NSString stringWithFormat:kFIRStorageAuthTokenFormat, token]; + [request setValue:firebaseToken forHTTPHeaderField:@"Authorization"]; + } + dispatch_async(callbackQueue, ^{ + [invocation invoke]; + }); + }]; + } else { + dispatch_async(callbackQueue, ^{ + [invocation invoke]; + }); + } + } +} + +// Note that stopAuthorization, isAuthorizingRequest, and userEmail +// aren't relevant with the Firebase App/Auth implementation of tokens, +// and thus aren't implemented. Token refresh is handled transparently +// for us, and we don't allow the auth request to be stopped. +// Auth is also not required so the world doesn't stop. +- (void)stopAuthorization { + // Noop +} + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request { + // Noop +} + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request { + return NO; +} + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request { + NSString *authHeader = request.allHTTPHeaderFields[@"Authorization"]; + BOOL isFirebaseToken = [authHeader hasPrefix:@"Firebase"]; + return isFirebaseToken; +} + +- (NSString *)userEmail { + // Noop + return nil; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h new file mode 100644 index 00000000..fb60fc5c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability update the metadata on an object in Firebase Storage. + */ +@interface FIRStorageUpdateMetadataTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + metadata:(FIRStorageMetadata *)metadata + completion:(FIRStorageVoidMetadataError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m new file mode 100644 index 00000000..d091b7ca --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m @@ -0,0 +1,107 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h" + +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageUpdateMetadataTask { + @private + FIRStorageVoidMetadataError _completion; + // Metadata used in the update request + FIRStorageMetadata *_updateMetadata; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + metadata:(FIRStorageMetadata *)metadata + completion:(FIRStorageVoidMetadataError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _updateMetadata = [metadata copy]; + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageUpdateMetadataTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageUpdateMetadataTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + NSDictionary *updateDictionary = [strongSelf->_updateMetadata updatedMetadata]; + NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary]; + request.HTTPMethod = @"PATCH"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + request.HTTPBody = updateData; + NSString *typeString = @"application/json; charset=UTF-8"; + [request setValue:typeString forHTTPHeaderField:@"Content-Type"]; + NSString *lengthString = [NSString stringWithFormat:@"%zu", (unsigned long)[updateData length]]; + [request setValue:lengthString forHTTPHeaderField:@"Content-Length"]; + + FIRStorageVoidMetadataError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(metadata, self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + fetcher.comment = @"UpdateMetadataTask"; + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m new file mode 100644 index 00000000..18a67656 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m @@ -0,0 +1,271 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h" + +#import + +@implementation FIRStorageUploadTask + +@synthesize progress = _progress; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + data:(NSData *)uploadData + metadata:(FIRStorageMetadata *)metadata { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _uploadMetadata = [metadata copy]; + _uploadData = [uploadData copy]; + _progress = [NSProgress progressWithTotalUnitCount:[_uploadData length]]; + + if (!_uploadMetadata.contentType) { + _uploadMetadata.contentType = @"application/octet-stream"; + } + } + return self; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(NSURL *)fileURL + metadata:(FIRStorageMetadata *)metadata { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _uploadMetadata = [metadata copy]; + _fileURL = [fileURL copy]; + _progress = [NSProgress progressWithTotalUnitCount:0]; + + NSString *mimeType = [FIRStorageUtils MIMETypeForExtension:[_fileURL pathExtension]]; + + if (!_uploadMetadata.contentType) { + _uploadMetadata.contentType = mimeType ?: @"application/octet-stream"; + } + } + return self; +} + +- (void)dealloc { + [_uploadFetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageUploadTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSError *contentValidationError; + if (![strongSelf isContentToUploadValid:&contentValidationError]) { + strongSelf.error = contentValidationError; + [strongSelf finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:strongSelf.snapshot]; + return; + } + + strongSelf.state = FIRStorageTaskStateQueueing; + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"POST"; + request.timeoutInterval = strongSelf.reference.storage.maxUploadRetryTime; + NSData *bodyData = + [NSData frs_dataFromJSONDictionary:[strongSelf->_uploadMetadata dictionaryRepresentation]]; + request.HTTPBody = bodyData; + [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; + NSString *contentLengthString = + [NSString stringWithFormat:@"%zu", (unsigned long)[bodyData length]]; + [request setValue:contentLengthString forHTTPHeaderField:@"Content-Length"]; + + NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL + resolvingAgainstBaseURL:NO]; + + if ([components.host isEqual:kGCSHost]) { + [components setPercentEncodedPath:[@"/upload" stringByAppendingString:components.path]]; + } + + NSDictionary *queryParams = @{@"uploadType" : @"resumable", @"name" : self.uploadMetadata.path}; + [components setPercentEncodedQuery:[FIRStorageUtils queryStringForDictionary:queryParams]]; + request.URL = components.URL; + + GTMSessionUploadFetcher *uploadFetcher = + [GTMSessionUploadFetcher uploadFetcherWithRequest:request + uploadMIMEType:strongSelf->_uploadMetadata.contentType + chunkSize:kGTMSessionUploadFetcherStandardChunkSize + fetcherService:self.fetcherService]; + + if (strongSelf->_uploadData) { + [uploadFetcher setUploadData:strongSelf->_uploadData]; + uploadFetcher.comment = @"Data UploadTask"; + } else if (strongSelf->_fileURL) { + [uploadFetcher setUploadFileURL:strongSelf->_fileURL]; + uploadFetcher.comment = @"File UploadTask"; + } + + uploadFetcher.maxRetryInterval = self.reference.storage.maxUploadRetryTime; + + [uploadFetcher setSendProgressBlock:^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesSent; + weakSelf.progress.totalUnitCount = totalBytesExpectedToSend; + weakSelf.metadata = self->_uploadMetadata; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:weakSelf.snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + + strongSelf->_uploadFetcher = uploadFetcher; + + // Process fetches + strongSelf.state = FIRStorageTaskStateRunning; + + strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) { + // Fire last progress updates + [self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot]; + + // Handle potential issues with upload + if (error) { + self.state = FIRStorageTaskStateFailed; + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + self.metadata = self->_uploadMetadata; + + [self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; + return; + } + + // Upload completed successfully, fire completion callbacks + self.state = FIRStorageTaskStateSuccess; + + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary) { + FIRStorageMetadata *metadata = + [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + self.metadata = metadata; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + + [self finishTaskWithStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; + }; + + [strongSelf->_uploadFetcher + beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) { + if (weakSelf.fetcherCompletion != nil) { + weakSelf.fetcherCompletion(data, error); + } + }]; + }]; +} + +- (void)finishTaskWithStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot { + [self fireHandlersForStatus:status snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; +} + +- (BOOL)isContentToUploadValid:(NSError **)outError { + if (_uploadData != nil) { + return YES; + } + + NSError *fileReachabilityError; + if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError] || + ![self fileURLisFile:_fileURL]) { + if (outError != NULL) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:2]; + userInfo[NSLocalizedDescriptionKey] = [NSString + stringWithFormat:@"File at URL: %@ is not reachable. " + @"Ensure file URL is not a directory, symbolic link, or invalid url.", + _fileURL.absoluteString]; + + if (fileReachabilityError) { + userInfo[NSUnderlyingErrorKey] = fileReachabilityError; + } + + *outError = [NSError errorWithDomain:FIRStorageErrorDomain + code:FIRStorageErrorCodeUnknown + userInfo:userInfo]; + } + + return NO; + } + + return YES; +} + +#pragma mark - Upload Management + +- (void)cancel { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateCancelled; + [weakSelf.uploadFetcher stopFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + weakSelf.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled]; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot]; + }]; +} + +- (void)pause { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStatePaused; + [weakSelf.uploadFetcher pauseFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:weakSelf.snapshot]; + }]; +} + +- (void)resume { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateResuming; + [weakSelf.uploadFetcher resumeFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:weakSelf.snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; +} + +#pragma mark - Private Helpers + +- (BOOL)fileURLisFile:(NSURL *)fileURL { + NSNumber *isFile = [NSNumber numberWithBool:NO]; + [fileURL getResourceValue:&isFile forKey:NSURLIsRegularFileKey error:nil]; + return [isFile boolValue]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h new file mode 100644 index 00000000..8d37a8b6 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@class GTMSessionUploadFetcher; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageUploadTask () + +/** + * The data to be uploaded (if uploading bytes). + */ +@property(readonly, copy, nonatomic, nullable) NSData *uploadData; + +/** + * The name of a file on disk to be uploaded (if uploading from a file). + */ +@property(readonly, copy, nonatomic, nullable) NSURL *fileURL; + +/** + * The FIRStorageMetadata about the object being uploaded. + */ +@property(readonly, copy, nonatomic) FIRStorageMetadata *uploadMetadata; + +/** + * GTMSessionUploadFetcher used by all uploads. + */ +@property(strong, atomic) GTMSessionUploadFetcher *uploadFetcher; + +/** + * Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param uploadData The NSData object to be uploaded. + * @return Returns an instance of FIRStorageUploadTask. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + data:(NSData *)uploadData + metadata:(FIRStorageMetadata *)metadata; + +/** + * Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param fileURL The system file URL to upload from. + * @return Returns an instance of FIRStorageUploadTask. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(NSURL *)fileURL + metadata:(FIRStorageMetadata *)metadata; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h new file mode 100644 index 00000000..55dfab09 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStoragePath; + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageUtils provides a number of helper methods for commonly used operations + * in Firebase Storage, such as JSON parsing, escaping, and file extensions. + */ +@interface FIRStorageUtils : NSObject + +/** + * Returns a percent encoded string appropriate for GCS. + * See https://cloud.google.com/storage/docs/naming for more details. + * @param string A path to escape characters according to the GCS + * @return A percent encoded string appropriate for GCS operations or nil if string is nil + * or can't be escaped. + */ ++ (nullable NSString *)GCSEscapedString:(NSString *)string; + +/** + * Returns the MIME type for a file extension. + * Example of how to get MIME type here: http://ddeville.me/2011/12/mime-to-UTI-cocoa/ + * @param extension A file extension such as "txt", "png", etc. + * @return The MIME type for the input extension such as "text/plain", "image/png", etc. + * or nil if no type is found. + */ ++ (nullable NSString *)MIMETypeForExtension:(NSString *)extension; + +/** + * Returns a properly escaped query string from a given dictionary of query items to values. + * @param dictionary A dictionary containing query items and associated values. + * @return A properly escaped query string or the empty string for a nil or empty dictionary. + */ ++ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary; + +/** + * Returns a base NSURLRequest used by all tasks. + * @param path The FIRStoragePath to create a request for. + * @return Returns a properly formatted NSURLRequest of the form: + * scheme://host/version/b//o[/path/to/object] + */ ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path; + +/** + * Returns a base NSURLRequest with custom query parameters. + * @param path The FIRStoragePath to create a request for. + * @param queryParams A key/value dictionary with query parameters. + * @return Returns a formatted NSURLRequest + */ ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path + queryParams:(NSDictionary *)queryParams; + +/** + * Creates the appropriate GCS percent escaped path for a given FIRStoragePath. + * @param path The FIRStoragePath to encode. + * @return Returns the GCS encoded URL for a given FIRStoragePath. + */ ++ (NSString *)encodedURLForPath:(FIRStoragePath *)path; + +/** + * Creates a NSError in the Firebase Storage domain with given code and description. + * Useful for argument validation. + * @param description The error description to surface to the user. + * @param code The error code. + * @return An NSError in the Firebase Storage error domain. + */ ++ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code; + +@end + +@interface NSDictionary (FIRStorageNSDictionaryJSONHelpers) + +/** + * Returns a dictionary representation of the data in @a data. + * @param data NSData containing JSON data. + * @return An NSDictionary representation of the JSON, or nil if serialization failed. + */ ++ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data; + +@end + +@interface NSData (FIRStorageNSDataJSONHelpers) + +/** + * Returns an NSData instance containing JSON serialized from @a dictionary. + * @param dictionary An NSDictionary containing only types serializable to JSON. + * @return An NSData object representing the binary JSON, or nil if serialization failed. + */ ++ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m new file mode 100644 index 00000000..443b26dc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m @@ -0,0 +1,151 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX || TARGET_OS_WATCH +#import +#endif + +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +#import + +// This is the list at https://cloud.google.com/storage/docs/json_api/ without &, ; and +. +NSString *const kGCSObjectAllowedCharacterSet = + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*,=:@"; + +@implementation FIRStorageUtils + ++ (nullable NSString *)GCSEscapedString:(NSString *)string { + NSCharacterSet *allowedCharacters = + [NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet]; + + return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; +} + ++ (nullable NSString *)MIMETypeForExtension:(NSString *)extension { + if (extension == nil) { + return nil; + } + + CFStringRef pathExtension = (__bridge_retained CFStringRef)extension; + CFStringRef type = + UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL); + NSString *mimeType = + (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType); + CFRelease(pathExtension); + if (type != NULL) { + CFRelease(type); + } + + return mimeType; +} + ++ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary { + if (!dictionary) { + return @""; + } + + __block NSMutableArray *queryItems = [[NSMutableArray alloc] initWithCapacity:[dictionary count]]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value, + BOOL *_Nonnull stop) { + NSString *item = + [FIRStorageUtils GCSEscapedString:[NSString stringWithFormat:@"%@=%@", name, value]]; + [queryItems addObject:item]; + }]; + return [queryItems componentsJoinedByString:@"&"]; +} + ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path { + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSURLComponents *components = [[NSURLComponents alloc] init]; + [components setScheme:kFIRStorageScheme]; + [components setHost:kFIRStorageHost]; + NSString *encodedPath = [self encodedURLForPath:path]; + [components setPercentEncodedPath:encodedPath]; + [request setURL:components.URL]; + return request; +} + ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path + queryParams:(NSDictionary *)queryParams { + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSURLComponents *components = [[NSURLComponents alloc] init]; + [components setScheme:kFIRStorageScheme]; + [components setHost:kFIRStorageHost]; + + NSMutableArray *queryItems = [NSMutableArray new]; + for (NSString *key in queryParams) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryParams[key]]]; + } + [components setQueryItems:queryItems]; + + NSString *encodedPath = [self encodedURLForPath:path]; + [components setPercentEncodedPath:encodedPath]; + [request setURL:components.URL]; + return request; +} + ++ (NSString *)encodedURLForPath:(FIRStoragePath *)path { + NSString *bucketName = [FIRStorageUtils GCSEscapedString:path.bucket]; + NSString *objectName = [FIRStorageUtils GCSEscapedString:path.object]; + NSString *bucketFormat = [NSString stringWithFormat:kFIRStorageBucketPathFormat, bucketName]; + NSString *urlPath = [@"/" stringByAppendingPathComponent:bucketFormat]; + if (objectName) { + NSString *objectFormat = [NSString stringWithFormat:kFIRStorageObjectPathFormat, objectName]; + urlPath = [urlPath stringByAppendingFormat:@"/%@", objectFormat]; + } else { + urlPath = [urlPath stringByAppendingString:@"/o"]; + } + return [@"/" stringByAppendingString:[kFIRStorageVersionPath stringByAppendingString:urlPath]]; +} + ++ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code { + return [NSError errorWithDomain:FIRStorageErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : description}]; +} + +@end + +@implementation NSDictionary (FIRStorageNSDictionaryJSONHelpers) + ++ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data { + if (!data) { + return nil; + } + return [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableContainers + error:nil]; +} + +@end + +@implementation NSData (FIRStorageNSDataJSONHelpers) + ++ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary { + if (!dictionary) { + return nil; + } + return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h new file mode 100644 index 00000000..04cecc14 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@class FIRApp; +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorage () + +@property(strong, nonatomic, readwrite) FIRApp *app; + +@property(strong, nonatomic) GTMSessionFetcherService *fetcherServiceForApp; + +@property(nonatomic, readonly) dispatch_queue_t dispatchQueue; + +@property(strong, nonatomic) NSString *storageBucket; + +/** + * Enables/disables GTMSessionFetcher HTTP logging + * @param isLoggingEnabled Boolean passed through to enable/disable GTMSessionFetcher logging + */ ++ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h new file mode 100644 index 00000000..85eb25da --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h @@ -0,0 +1,130 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" + +@class FIRApp; +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** Project version string for FirebaseStorage. */ +FOUNDATION_EXPORT const char *const FIRStorageVersionString NS_SWIFT_NAME(StorageVersionString); + +/** + * FirebaseStorage is a service that supports uploading and downloading binary objects, + * such as images, videos, and other files to Google Cloud Storage. + * + * If you call [FIRStorage storage], the instance will initialize with the default FIRApp, + * [FIRApp defaultApp], and the storage location will come from the provided + * GoogleService-Info.plist. + * + * If you call [FIRStorage storageForApp:] and provide a custom instance of FIRApp, + * the storage location will be specified via the FIROptions#storageBucket property. + */ +NS_SWIFT_NAME(Storage) +@interface FIRStorage : NSObject + +/** + * Creates an instance of FIRStorage, configured with the default FIRApp. + * @return the FIRStorage instance, initialized with the default FIRApp. + */ ++ (instancetype)storage NS_SWIFT_NAME(storage()); + +/** + * Creates an instance of FIRStorage, configured with the custom FIRApp @a app. + * @param app The custom FIRApp used for initialization. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageForApp:(FIRApp *)app NS_SWIFT_NAME(storage(app:)); + +/** + * Creates an instance of FIRStorage, configured with a custom storage bucket @a url. + * @param url The gs:// url to your Firebase Storage Bucket. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageWithURL:(NSString *)url NS_SWIFT_NAME(storage(url:)); + +/** + * Creates an instance of FIRStorage, configured with a custom FIRApp @a app and a custom storage + * bucket @a url. + * @param app The custom FIRApp used for initialization. + * @param url The gs:// url to your Firebase Storage Bucket. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url NS_SWIFT_NAME(storage(app:url:)); + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The Firebase App associated with this Firebase Storage instance. + */ +@property(strong, nonatomic, readonly) FIRApp *app; + +/** + * Maximum time in seconds to retry an upload if a failure occurs. + * Defaults to 10 minutes (600 seconds). + */ +@property NSTimeInterval maxUploadRetryTime; + +/** + * Maximum time in seconds to retry a download if a failure occurs. + * Defaults to 10 minutes (600 seconds). + */ +@property NSTimeInterval maxDownloadRetryTime; + +/** + * Maximum time in seconds to retry operations other than upload and download if a failure occurs. + * Defaults to 2 minutes (120 seconds). + */ +@property NSTimeInterval maxOperationRetryTime; + +/** + * Queue that all developer callbacks are fired on. Defaults to the main queue. + */ +@property(strong, nonatomic) dispatch_queue_t callbackQueue; + +/** + * Creates a FIRStorageReference initialized at the root Firebase Storage location. + * @return An instance of FIRStorageReference initialized at the root. + */ +- (FIRStorageReference *)reference; + +/** + * Creates a FIRStorageReference given a gs:// or https:// URL pointing to a Firebase Storage + * location. For example, you can pass in an https:// download URL retrieved from + * [FIRStorageReference downloadURLWithCompletion] or the gs:// URI from + * [FIRStorageReference description]. + * @param string A gs:// or https:// URL to initialize the reference with. + * @return An instance of FIRStorageReference at the given child path. + * @throws Throws an exception if passed in URL is not associated with the FIRApp used to initialize + * this FIRStorage. + */ +- (FIRStorageReference *)referenceForURL:(NSString *)string; + +/** + * Creates a FIRStorageReference initialized at a child Firebase Storage location. + * @param string A relative path from the root to initialize the reference with, + * for instance @"path/to/object". + * @return An instance of FIRStorageReference at the given child path. + */ +- (FIRStorageReference *)referenceWithPath:(NSString *)string; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h new file mode 100644 index 00000000..52c73826 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h @@ -0,0 +1,174 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageDownloadTask; +@class FIRStorageMetadata; +@class FIRStorageTaskSnapshot; +@class FIRStorageUploadTask; + +NS_ASSUME_NONNULL_BEGIN + +/** + * NSString typedef representing a task listener handle. + */ +typedef NSString *FIRStorageHandle NS_SWIFT_NAME(StorageHandle); + +/** + * Block typedef typically used when downloading data. + * @param data The data returned by the download, or nil if no data available or download failed. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidDataError)(NSData *_Nullable data, NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidDataError); + +/** + * Block typedef typically used when performing "binary" async operations such as delete, + * where the operation either succeeds without an error or fails with an error. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidError)(NSError *_Nullable error) NS_SWIFT_NAME(StorageVoidError); + +/** + * Block typedef typically used when retrieving metadata. + * @param metadata The metadata returned by the operation, if metadata exists. + */ +typedef void (^FIRStorageVoidMetadata)(FIRStorageMetadata *_Nullable metadata) + NS_SWIFT_NAME(StorageVoidMetadata); + +/** + * Block typedef typically used when retrieving metadata with the possibility of an error. + * @param metadata The metadata returned by the operation, if metadata exists. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidMetadataError)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidMetadataError); + +/** + * Block typedef typically used to asynchronously return a storage task snapshot. + * @param snapshot The returned task snapshot. + */ +typedef void (^FIRStorageVoidSnapshot)(FIRStorageTaskSnapshot *snapshot) + NS_SWIFT_NAME(StorageVoidSnapshot); + +/** + * Block typedef typically used when retrieving a download URL. + * @param URL The download URL associated with the operation. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidURLError)(NSURL *_Nullable URL, NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidURLError); + +/** + * Enum representing the upload and download task status. + */ +typedef NS_ENUM(NSInteger, FIRStorageTaskStatus) { + /** + * Unknown task status. + */ + FIRStorageTaskStatusUnknown, + + /** + * Task is being resumed. + */ + FIRStorageTaskStatusResume, + + /** + * Task reported a progress event. + */ + FIRStorageTaskStatusProgress, + + /** + * Task is paused. + */ + FIRStorageTaskStatusPause, + + /** + * Task has completed successfully. + */ + FIRStorageTaskStatusSuccess, + + /** + * Task has failed and is unrecoverable. + */ + FIRStorageTaskStatusFailure +} NS_SWIFT_NAME(StorageTaskStatus); + +/** + * Firebase Storage error domain. + */ +FOUNDATION_EXPORT NSString *const FIRStorageErrorDomain NS_SWIFT_NAME(StorageErrorDomain); + +/** + * Enum representing the errors raised by Firebase Storage. + */ +typedef NS_ENUM(NSInteger, FIRStorageErrorCode) { + /** An unknown error occurred. */ + FIRStorageErrorCodeUnknown = -13000, + + /** No object exists at the desired reference. */ + FIRStorageErrorCodeObjectNotFound = -13010, + + /** No bucket is configured for Firebase Storage. */ + FIRStorageErrorCodeBucketNotFound = -13011, + + /** No project is configured for Firebase Storage. */ + FIRStorageErrorCodeProjectNotFound = -13012, + + /** + * Quota on your Firebase Storage bucket has been exceeded. + * If you're on the free tier, upgrade to a paid plan. + * If you're on a paid plan, reach out to Firebase support. + */ + FIRStorageErrorCodeQuotaExceeded = -13013, + + /** User is unauthenticated. Authenticate and try again. */ + FIRStorageErrorCodeUnauthenticated = -13020, + + /** + * User is not authorized to perform the desired action. + * Check your rules to ensure they are correct. + */ + FIRStorageErrorCodeUnauthorized = -13021, + + /** + * The maximum time limit on an operation (upload, download, delete, etc.) has been exceeded. + * Try uploading again. + */ + FIRStorageErrorCodeRetryLimitExceeded = -13030, + + /** + * File on the client does not match the checksum of the file received by the server. + * Try uploading again. + */ + FIRStorageErrorCodeNonMatchingChecksum = -13031, + + /** + * Size of the downloaded file exceeds the amount of memory allocated for the download. + * Increase memory cap and try downloading again. + */ + FIRStorageErrorCodeDownloadSizeExceeded = -13032, + + /** User cancelled the operation. */ + FIRStorageErrorCodeCancelled = -13040, + + /** An invalid argument was provided. */ + FIRStorageErrorCodeInvalidArgument = -13050 +} NS_SWIFT_NAME(StorageErrorCode); + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h new file mode 100644 index 00000000..c11373f0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageObservableTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageDownloadTask implements resumable downloads from an object in Firebase Storage. + * Downloads can be returned on completion with a completion handler, and can be monitored + * by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume, + * or FIRStorageTask#cancel. + * Downloads can currently be returned as NSData in memory, or as an NSURL to a file on disk. + * Downloads are performed on a background queue, and callbacks are raised on the developer + * specified callbackQueue in FIRStorage, or the main queue if left unspecified. + * Currently all uploads must be initiated and managed on the main queue. + */ +NS_SWIFT_NAME(StorageDownloadTask) +@interface FIRStorageDownloadTask : FIRStorageObservableTask + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h new file mode 100644 index 00000000..0207c51c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** Contains the prefixes and items returned by a `StorageReference.list()` call. */ +NS_SWIFT_NAME(StorageListResult) +@interface FIRStorageListResult : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The prefixes (folders) returned by the `list()` operation. + * + * @return A list of prefixes (folders). + */ +@property(nonatomic, readonly) NSArray *prefixes; + +/** + * The items (files) returned by the `list()` operation. + * + * @return A list of items (files). + */ +@property(nonatomic, readonly) NSArray *items; + +/** + * Returns a token that can be used to resume a previous `list()` operation. `nil` + * indicates that there are no more results. + * + * @return A page token if more results are available. + */ +@property(nonatomic, readonly, nullable) NSString *pageToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h new file mode 100644 index 00000000..3749504e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Class which represents the metadata on an object in Firebase Storage. This metadata is + * returned on successful operations, and can be used to retrieve download URLs, content types, + * and a FIRStorage reference to the object in question. Full documentation can be found at the GCS + * Objects#resource docs. + * @see https://cloud.google.com/storage/docs/json_api/v1/objects#resource + */ +NS_SWIFT_NAME(StorageMetadata) +@interface FIRStorageMetadata : NSObject + +/** + * The name of the bucket containing this object. + */ +@property(copy, nonatomic, readonly) NSString *bucket; + +/** + * Cache-Control directive for the object data. + */ +@property(copy, nonatomic, nullable) NSString *cacheControl; + +/** + * Content-Disposition of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentDisposition; + +/** + * Content-Encoding of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentEncoding; + +/** + * Content-Language of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentLanguage; + +/** + * Content-Type of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentType; + +/** + * MD5 hash of the data; encoded using base64. + */ +@property(copy, nonatomic, nullable, readonly) NSString *md5Hash; + +/** + * The content generation of this object. Used for object versioning. + */ +@property(readonly) int64_t generation; + +/** + * User-provided metadata, in key/value pairs. + */ +@property(copy, nonatomic, nullable) NSDictionary *customMetadata; + +/** + * The version of the metadata for this object at this generation. Used + * for preconditions and for detecting changes in metadata. A metageneration number is only + * meaningful in the context of a particular generation of a particular object. + */ +@property(readonly) int64_t metageneration; + +/** + * The name of this object, in gs://bucket/path/to/object.txt, this is object.txt. + */ +@property(copy, nonatomic, readonly, nullable) NSString *name; + +/** + * The full path of this object, in gs://bucket/path/to/object.txt, this is path/to/object.txt. + */ +@property(copy, nonatomic, readonly, nullable) NSString *path; + +/** + * Content-Length of the data in bytes. + */ +@property(readonly) int64_t size; + +/** + * The creation time of the object in RFC 3339 format. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *timeCreated; + +/** + * The modification time of the object metadata in RFC 3339 format. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *updated; + +/** + * A reference to the object in Firebase Storage. + */ +@property(strong, nonatomic, readonly, nullable) FIRStorageReference *storageReference; + +/** + * Creates an instance of FIRStorageMetadata from the contents of a dictionary. + * @return An instance of FIRStorageMetadata that represents the contents of a dictionary. + */ +- (nullable instancetype)initWithDictionary:(NSDictionary *)dictionary + NS_DESIGNATED_INITIALIZER; + +/** + * Creates an NSDictionary from the contents of the metadata. + * @return An NSDictionary that represents the contents of the metadata. + */ +- (NSDictionary *)dictionaryRepresentation; + +/** + * Determines if the current metadata represents a "file". + */ +@property(readonly, getter=isFile) BOOL file; + +/** + * Determines if the current metadata represents a "folder". + */ +@property(readonly, getter=isFolder) BOOL folder; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h new file mode 100644 index 00000000..d8ad401c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRStorageTask.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; +@class FIRStorageTaskSnapshot; + +/** + * Extends FIRStorageTask to provide observable semantics such as adding and removing observers. + * Observers produce a FIRStorageHandle, which is used to keep track of and remove specific + * observers at a later date. + * This class is currently not thread safe and can only be called on the main thread. + */ +NS_SWIFT_NAME(StorageObservableTask) +@interface FIRStorageObservableTask : FIRStorageTask + +/** + * Observes changes in the upload status: Resume, Pause, Progress, Success, and Failure. + * @param status The FIRStorageTaskStatus change to observe. + * @param handler A callback that fires every time the status event occurs, + * returns a FIRStorageTaskSnapshot containing the state of the task. + * @return A task handle that can be used to remove the observer at a later date. + */ +- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status + handler:(void (^)(FIRStorageTaskSnapshot *snapshot))handler; + +/** + * Removes the single observer with the provided handle. + * @param handle The handle of the task to remove. + */ +- (void)removeObserverWithHandle:(FIRStorageHandle)handle; + +/** + * Removes all observers for a single status. + * @param status A FIRStorageTaskStatus to remove listeners for. + */ +- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status; + +/** + * Removes all observers. + */ +- (void)removeAllObservers; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h new file mode 100644 index 00000000..94b1c89c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h @@ -0,0 +1,313 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageTask.h" +#import "FIRStorageUploadTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageReference represents a reference to a Google Cloud Storage object. Developers can + * upload and download objects, as well as get/set object metadata, and delete an object at the + * path. + * @see https://cloud.google.com/storage/ + */ +NS_SWIFT_NAME(StorageReference) +@interface FIRStorageReference : NSObject + +/** + * The FIRStorage service object which created this reference. + */ +@property(nonatomic, readonly) FIRStorage *storage; + +/** + * The name of the Google Cloud Storage bucket associated with this reference, + * in gs://bucket/path/to/object.txt, the bucket would be: 'bucket' + */ +@property(nonatomic, readonly) NSString *bucket; + +/** + * The full path to this object, not including the Google Cloud Storage bucket. + * In gs://bucket/path/to/object.txt, the full path would be: 'path/to/object.txt' + */ +@property(nonatomic, readonly) NSString *fullPath; + +/** + * The short name of the object associated with this reference, + * in gs://bucket/path/to/object.txt, the name of the object would be: 'object.txt' + */ +@property(nonatomic, readonly) NSString *name; + +#pragma mark - Path Operations + +/** + * Creates a new FIRStorageReference pointing to the root object. + * @return A new FIRStorageReference pointing to the root object. + */ +- (FIRStorageReference *)root; + +/** + * Creates a new FIRStorageReference pointing to the parent of the current reference + * or nil if this instance references the root location. + * For example: + * path = foo/bar/baz parent = foo/bar + * path = foo parent = (root) + * path = (root) parent = nil + * @return A new FIRStorageReference pointing to the parent of the current reference. + */ +- (nullable FIRStorageReference *)parent; + +/** + * Creates a new FIRStorageReference pointing to a child object of the current reference. + * path = foo child = bar newPath = foo/bar + * path = foo/bar child = baz newPath = foo/bar/baz + * All leading and trailing slashes will be removed, and consecutive slashes will be + * compressed to single slashes. For example: + * child = /foo/bar newPath = foo/bar + * child = foo/bar/ newPath = foo/bar + * child = foo///bar newPath = foo/bar + * @param path Path to append to the current path. + * @return A new FIRStorageReference pointing to a child location of the current reference. + */ +- (FIRStorageReference *)child:(NSString *)path; + +#pragma mark - Uploads + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference, + * without additional metadata. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +- (FIRStorageUploadTask *)putData:(NSData *)uploadData NS_SWIFT_NAME(putData(_:)); + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata +NS_SWIFT_NAME(putData(_:metadata:)); +// clang-format on + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @param completion A completion block that either returns the object metadata on success, + * or an error on failure. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion + NS_SWIFT_NAME(putData(_:metadata:completion:)); +// clang-format on + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference, + * without additional metadata. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL NS_SWIFT_NAME(putFile(from:)); + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + NS_SWIFT_NAME(putFile(from:metadata:)); +// clang-format on + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @param completion A completion block that either returns the object metadata on success, + * or an error on failure. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion + NS_SWIFT_NAME(putFile(from:metadata:completion:)); +// clang-format on + +#pragma mark - Downloads + +/** + * Asynchronously downloads the object at the FIRStorageReference to an NSData object in memory. + * An NSData of the provided max size will be allocated, so ensure that the device has enough free + * memory to complete the download. For downloading large files, writeToFile may be a better option. + * @param size The maximum size in bytes to download. If the download exceeds this size + * the task will be cancelled and an error will be returned. + * @param completion A completion block that either returns the object data on success, + * or an error on failure. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +// clang-format off +- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size + completion:(void (^)(NSData *_Nullable data, + NSError *_Nullable error))completion + NS_SWIFT_NAME(getData(maxSize:completion:)); +// clang-format on + +/** + * Asynchronously retrieves a long lived download URL with a revokable token. + * This can be used to share the file with others, but can be revoked by a developer + * in the Firebase Console if desired. + * @param completion A completion block that either returns the URL on success, + * or an error on failure. + */ +- (void)downloadURLWithCompletion:(void (^)(NSURL *_Nullable URL, + NSError *_Nullable error))completion; + +/** + * Asynchronously downloads the object at the current path to a specified system filepath. + * @param fileURL A file system URL representing the path the object should be downloaded to. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL; + +/** + * Asynchronously downloads the object at the current path to a specified system filepath. + * @param fileURL A file system URL representing the path the object should be downloaded to. + * @param completion A completion block that fires when the file download completes. + * Returns an NSURL pointing to the file path of the downloaded file on success, + * or an error on failure. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL + completion:(nullable void (^)(NSURL *_Nullable URL, + NSError *_Nullable error))completion; +#pragma mark - List Support + +/** + * List all items (files) and prefixes (folders) under this StorageReference. + * + * This is a helper method for calling list() repeatedly until there are no more results. + * Consistency of the result is not guaranteed if objects are inserted or removed while this + * operation is executing. All results are buffered in memory. + * + * `listAll(completion:)` is only available for projects using Firebase Rules Version 2. + * + * @param completion A completion handler that will be invoked with all items and prefixes under + * the current StorageReference. + */ +- (void)listAllWithCompletion:(void (^)(FIRStorageListResult *result, + NSError *_Nullable error))completion; + +/** + * List up to `maxResults` items (files) and prefixes (folders) under this StorageReference. + * + * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object + * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be + * filtered. + * + * `list(maxResults:completion:)` is only available for projects using Firebase Rules Version 2. + * + * @param maxResults The maximum number of results to return in a single page. Must be greater + * than 0 and at most 1000. + * @param completion A completion handler that will be invoked with up to maxResults items and + * prefixes under the current StorageReference. + */ +- (void)listWithMaxResults:(int64_t)maxResults + completion: + (void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion; + +/** + * Resumes a previous call to list(maxResults:completion:)`, starting after a pagination token. + * Returns the next set of items (files) and prefixes (folders) under this StorageReference. + * + * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object + * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be + * filtered. + * + * `list(maxResults:pageToken:completion:)`is only available for projects using Firebase Rules + * Version 2. + * + * @param maxResults The maximum number of results to return in a single page. Must be greater + * than 0 and at most 1000. + * @param pageToken A page token from a previous call to list. + * @param completion A completion handler that will be invoked with the next items and prefixes + * under the current StorageReference. + */ +- (void)listWithMaxResults:(int64_t)maxResults + pageToken:(NSString *)pageToken + completion: + (void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion; + +#pragma mark - Metadata Operations + +/** + * Retrieves metadata associated with an object at the current path. + * @param completion A completion block which returns the object metadata on success, + * or an error on failure. + */ +- (void)metadataWithCompletion: + (void (^)(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error))completion + NS_SWIFT_NAME(getMetadata(completion:)); + +/** + * Updates the metadata associated with an object at the current path. + * @param metadata An FIRStorageMetadata object with the metadata to update. + * @param completion A completion block which returns the FIRStorageMetadata on success, + * or an error on failure. + */ +// clang-format off +- (void)updateMetadata:(FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion +NS_SWIFT_NAME(updateMetadata(_:completion:)); +// clang-format on + +#pragma mark - Delete + +/** + * Deletes the object at the current path. + * @param completion A completion block which returns nil on success, or an error on failure. + */ +- (void)deleteWithCompletion:(nullable void (^)(NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h new file mode 100644 index 00000000..e889d5eb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" +#import "FIRStorageMetadata.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * A superclass to all FIRStorage*Tasks, including FIRStorageUploadTask + * and FIRStorageDownloadTask, to provide state transitions, event raising, and common storage + * or metadata and errors. + * Callbacks are always fired on the developer specified callback queue. + * If no queue is specified by the developer, it defaults to the main queue. + * Currently not thread safe, so only call methods on the main thread. + */ +NS_SWIFT_NAME(StorageTask) +@interface FIRStorageTask : NSObject + +/** + * An immutable view of the task and associated metadata, progress, error, etc. + */ +@property(strong, readonly, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot; + +@end + +/** + * Defines task operations such as pause, resume, cancel, and enqueue for all tasks. + * All tasks are required to implement enqueue, which begins the task, and may optionally + * implement pause, resume, and cancel, which operate on the task to pause, resume, and cancel + * operations. + */ +NS_SWIFT_NAME(StorageTaskManagement) +@protocol FIRStorageTaskManagement + +@required +/** + * Prepares a task and begins execution. + */ +- (void)enqueue; + +@optional +/** + * Pauses a task currently in progress. + */ +- (void)pause; + +/** + * Cancels a task currently in progress. + */ +- (void)cancel; + +/** + * Resumes a task that is paused. + */ +- (void)resume; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h new file mode 100644 index 00000000..7d142024 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageMetadata; +@class FIRStorageReference; +@class FIRStorageTask; + +/** + * FIRStorageTaskSnapshot represents an immutable view of a task. + * A Snapshot contains a task, storage reference, metadata (if it exists), + * progress, and an error (if one occurred). + */ +NS_SWIFT_NAME(StorageTaskSnapshot) +@interface FIRStorageTaskSnapshot : NSObject + +/** + * Subclass of FIRStorageTask this snapshot represents. + */ +@property(readonly, copy, nonatomic) __kindof FIRStorageTask *task; + +/** + * Metadata returned by the task, or nil if no metadata returned. + */ +@property(readonly, copy, nonatomic, nullable) FIRStorageMetadata *metadata; + +/** + * FIRStorageReference this task is operates on. + */ +@property(readonly, copy, nonatomic) FIRStorageReference *reference; + +/** + * NSProgress object which tracks the progess of an upload or download. + */ +@property(readonly, strong, nonatomic, nullable) NSProgress *progress; + +/** + * Error during task execution, or nil if no error occurred. + */ +@property(readonly, copy, nonatomic, nullable) NSError *error; + +/** + * Status of the task. + */ +@property(readonly, nonatomic) FIRStorageTaskStatus status; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h new file mode 100644 index 00000000..c7535002 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageObservableTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageUploadTask implements resumable uploads to a file in Firebase Storage. + * Uploads can be returned on completion with a completion callback, and can be monitored + * by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume, + * or FIRStorageTask#cancel. + * Uploads can take NSData in memory, or an NSURL to a file on disk. + * Uploads are performed on a background queue, and callbacks are raised on the developer + * specified callbackQueue in FIRStorage, or the main queue if left unspecified. + * Currently all uploads must be initiated and managed on the main queue. + */ +NS_SWIFT_NAME(StorageUploadTask) +@interface FIRStorageUploadTask : FIRStorageObservableTask + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h new file mode 100644 index 00000000..be9ee240 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageObservableTask.h" +#import "FIRStorageReference.h" +#import "FIRStorageTask.h" +#import "FIRStorageTaskSnapshot.h" +#import "FIRStorageUploadTask.h" diff --git a/MyExperiences copy/Pods/FirebaseStorage/Interop/Auth/Public/FIRAuthInterop.h b/MyExperiences copy/Pods/FirebaseStorage/Interop/Auth/Public/FIRAuthInterop.h new file mode 100644 index 00000000..a33da7c9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/Interop/Auth/Public/FIRAuthInterop.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRAuthInterop_h +#define FIRAuthInterop_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRTokenCallback + @brief The type of block which gets called when a token is ready. + */ +typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(TokenCallback); + +/// Common methods for Auth interoperability. +NS_SWIFT_NAME(AuthInterop) +@protocol FIRAuthInterop + +/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired. +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback; + +/// Get the current Auth user's UID. Returns nil if there is no user signed in. +- (nullable NSString *)getUserID; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRAuthInterop_h */ diff --git a/MyExperiences copy/Pods/FirebaseStorage/LICENSE b/MyExperiences copy/Pods/FirebaseStorage/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseStorage/README.md b/MyExperiences copy/Pods/FirebaseStorage/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseStorage/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.h new file mode 100644 index 00000000..13b1865d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.h @@ -0,0 +1,103 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@import Foundation; + +@class FIRAuth; +@class FIRUser; +@class FUIAuth; +@class UIViewController; + +NS_ASSUME_NONNULL_BEGIN + +/** @protocol FUIAccountSettingsOperationUIDelegate + @brief A delegate that provides UI methods for @c FUIAccountSettingsOperation. + */ +@protocol FUIAccountSettingsOperationUIDelegate + +/** @property auth + @brief The @c FIRAuth instance of the application. + */ +@property(nonatomic, strong, readonly) FIRAuth *auth; + +/** @property authUI + @brief The @c FUIAuth instance of the application. + */ +@property(nonatomic, strong, readonly) FUIAuth *authUI; + +/** @fn incrementActivity + @brief Increment the current activity count. If there's positive number of activities, display + and animate the activity indicator with a short period of delay. + @remarks Calls to @c incrementActivity and @c decrementActivity should be balanced. + */ +- (void)incrementActivity; + +/** @fn decrementActivity + @brief Decrement the current activity count. If the count reaches 0, stop and hide the + activity indicator. + @remarks Calls to @c incrementActivity and @c decrementActivity should be balanced. + */ +- (void)decrementActivity; + +/** @fn presentBaseController + @brief Called when initial Account Settings controller needs to be presented. + */ +- (void)presentBaseController; + +/** @fn presentViewController: + @brief Presents (pops) @c UIViewController from navigation stack. + */ +- (void)presentViewController:(UIViewController *)controller; + +/** @fn pushViewController: + @brief Adds (pushes) @c UIViewController to navigation stack. + */ +- (void)pushViewController:(UIViewController *)controller; + +/** @fn presentingController + @brief Provides access to presenting controller. + */ +- (UIViewController *)presentingController; + +@end + +/** @class FUIAccountSettingsOperation + @brief Handles logic for every specific user operation. + */ +@interface FUIAccountSettingsOperation : NSObject + +/** @fn executeOperationWithDelegate:showDialog: + @brief Creates new instance of @c FUIAccountSettingsOperation and executes logic + associated with it. + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog; + +/** @fn executeOperationWithDelegate: + @brief Creates new instance of @c FUIAccountSettingsOperation and executes logic + associated with it. New flow is started with new view. + @param delegate UI delegate which handles all UI related logic. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.m new file mode 100644 index 00000000..e70f47dc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.m @@ -0,0 +1,274 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation_Internal.h" + +#import "FUIAccountSettingsOperationDeleteAccount.h" +#import "FUIAccountSettingsOperationForgotPassword.h" +#import "FUIAccountSettingsOperationSignOut.h" +#import "FUIAccountSettingsOperationUnlinkAccount.h" +#import "FUIAccountSettingsOperationUpdateEmail.h" +#import "FUIAccountSettingsOperationUpdateName.h" +#import "FUIAccountSettingsOperationUpdatePassword.h" +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthErrorUtils.h" +#import "FUIAuth_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperation + ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog { + FUIAccountSettingsOperation *operation = [[self alloc] initWithDelegate:delegate]; + [operation execute:showDialog]; + return operation; +} + ++ (instancetype)executeOperationWithDelegate:(id)delegate { + FUIAccountSettingsOperation *operation = [[self alloc] initWithDelegate:delegate]; + [operation execute:NO]; + return operation; +} + +- (instancetype)initWithDelegate:(id)operationDelegate { + if (self = [super init]) { + _delegate = operationDelegate; + } + return self; +} + +- (void)execute:(BOOL)showDialog { + NSAssert(NO, @"Expected execute: to be overwritten by subclass"); +} + +- (FUIAccountSettingsOperationType)operationType { + NSAssert(NO, @"Expected execute: to be overwritten by subclass"); + return FUIAccountSettingsOperationTypeUnsupported; +} + +#pragma mark - protected methods + +- (void)finishOperationWithError:(nullable NSError *)error { + if (error) { + switch (error.code) { + case FIRAuthErrorCodeEmailAlreadyInUse: + [self showAlertWithMessage:FUILocalizedString(kStr_EmailAlreadyInUseError)]; + break; + case FIRAuthErrorCodeInvalidEmail: + [self showAlertWithMessage:FUILocalizedString(kStr_InvalidEmailError)]; + break; + case FIRAuthErrorCodeWeakPassword: + [self showAlertWithMessage:FUILocalizedString(kStr_WeakPasswordError)]; + break; + case FIRAuthErrorCodeTooManyRequests: + [self showAlertWithMessage:FUILocalizedString(kStr_SignUpTooManyTimesError)]; + break; + case FIRAuthErrorCodeWrongPassword: + [self showAlertWithMessage:FUILocalizedString(kStr_WrongPasswordError)]; + break; + case FIRAuthErrorCodeUserNotFound: + [self showAlertWithMessage:FUILocalizedString(kStr_UserNotFoundError)]; + break; + case FIRAuthErrorCodeUserDisabled: + [self showAlertWithMessage:FUILocalizedString(kStr_AccountDisabledError)]; + break; + case FUIAuthErrorCodeCantFindProvider: { + NSString *message = [NSString stringWithFormat:FUILocalizedString(kStr_CantFindProvider), + error.userInfo[FUIAuthErrorUserInfoProviderIDKey]]; + [self showAlertWithMessage:message]; + break; + } + case FIRAuthErrorCodeUserMismatch: + [self showAlertWithMessage:FUILocalizedString(kStr_EmailsDontMatch)]; + break; + } + } + + [self.delegate.authUI invokeOperationCallback:[self operationType] error:error]; +} + +- (void)showSelectProviderDialogWithAlertTitle:(nullable NSString *)title + alertMessage:(nullable NSString *)message + alertCloseButton:(nullable NSString *)closeActionTitle + providerHandler:(nullable FUIAccountSettingsChooseProviderHandler) + handler; { + UIAlertController *alert = + [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + for (id provider in self.delegate.auth.currentUser.providerData) { + NSString *providerTitle = + [NSString stringWithFormat:FUILocalizedString(kStr_SignInWithProvider), + [FUIAuthBaseViewController providerLocalizedName:provider.providerID]]; + UIAlertAction* action = [UIAlertAction actionWithTitle:providerTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + if (handler) { + handler(provider); + } + }]; + [alert addAction:action]; + } + UIAlertAction* closeButton = [UIAlertAction actionWithTitle:closeActionTitle + style:UIAlertActionStyleCancel + handler:nil]; + [alert addAction:closeButton]; + [self.delegate presentViewController:alert]; +} + +- (void)showAlertWithMessage:(NSString *)message { + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:nil + message:message + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:FUILocalizedString(kStr_OK) + style:UIAlertActionStyleDefault + handler:nil]; + [alertController addAction:okAction]; + [self.delegate presentViewController:alertController]; +} + +- (void)reauthenticateWithProvider:(NSString *)providerID + actionHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler { + + id providerUI; + for (id authProvider in self.delegate.authUI.providers) { + if ([providerID isEqualToString:authProvider.providerID]) { + providerUI = authProvider; + break; + } + } + + if (!providerUI) { + NSError *error = [FUIAuthErrorUtils errorWithCode:FUIAuthErrorCodeCantFindProvider + userInfo:@{ + FUIAuthErrorUserInfoProviderIDKey : providerID + }]; + [self finishOperationWithError:error]; + return; + } + + [self.delegate incrementActivity]; + // Sign out first to make sure sign in starts with a clean state. + [providerUI signOut]; + [providerUI signInWithDefaultValue:self.delegate.auth.currentUser.email + presentingViewController:[self.delegate presentingController] + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error, + _Nullable FIRAuthResultCallback result, + NSDictionary *_Nullable userInfo) { + if (error) { + [self.delegate decrementActivity]; + [self finishOperationWithError:error]; + if (result) { + result(nil, error); + } + return; + } + [self.delegate.auth.currentUser + reauthenticateWithCredential:credential + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable reauthError) { + [self.delegate decrementActivity]; + if (result) { + result(self.delegate.auth.currentUser, reauthError); + } + if (error) { + [self finishOperationWithError:error]; + } else { + if (handler) { + handler(); + [self finishOperationWithError:error]; + } + } + }]; + }]; +} + +- (void)reauthenticateWithPassword:(NSString *)password + actionHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler { + if (password.length <= 0) { + [self showAlertWithMessage:FUILocalizedString(kStr_InvalidPasswordError)]; + return; + } + + [self.delegate incrementActivity]; + + if (self.delegate.auth.currentUser.email == nil) { + NSLog(@"FirebaseUI: Expected nonnull email during email/password reauthentication"); + return; + } + [self.delegate.auth signInWithEmail:self.delegate.auth.currentUser.email + password:password + completion:^(FIRAuthDataResult *authResult, NSError *error) { + [self.delegate decrementActivity]; + + [self finishOperationWithError:error]; + if (!error && handler) { + handler(); + } + }]; +} + +- (void)showVerifyDialogWithMessage:(NSString *)message + providerHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler { + [self showSelectProviderDialogWithAlertTitle:FUILocalizedString(kStr_VerifyItsYou) + alertMessage:message + alertCloseButton:FUILocalizedString(kStr_Cancel) + providerHandler:^(id provider) { + if (![provider.providerID isEqualToString:FIREmailAuthProviderID]) { + [self reauthenticateWithProvider:provider.providerID actionHandler:handler]; + } else { + [self showVerifyPasswordViewWithMessage:message providerHandler:handler]; + } + }]; +} + +- (void)showVerifyPasswordViewWithMessage:(NSString *)message + providerHandler:(nullable FUIAccountSettingsReauthenticateHandler) + handler { + __block FUIStaticContentTableViewCell *passwordCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Password) + value:nil + placeholder:FUILocalizedString(kStr_PlaceholderEnterPassword) + type:FUIStaticContentTableViewCellTypePassword + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[passwordCell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:contents + nextTitle:FUILocalizedString(kStr_Next) + nextAction:^{ + [self reauthenticateWithPassword:passwordCell.value actionHandler:handler]; + } + headerText:message + footerText: + FUILocalizedString(kStr_ForgotPassword) + footerAction:^{ + [FUIAccountSettingsOperationForgotPassword executeOperationWithDelegate:self.delegate]; + }]; + controller.title = FUILocalizedString(kStr_VerifyItsYou); + [self.delegate pushViewController:controller]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.h new file mode 100644 index 00000000..15b75caf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationDeleteAccount + @brief Handles logic of account deletion operation. + */ +@interface FUIAccountSettingsOperationDeleteAccount : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate: + @brief Instead use @c executeOperationWithDelegate:showDialog: + @param delegate UI delegate which handles all UI related logic. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.m new file mode 100644 index 00000000..07ae7cd7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.m @@ -0,0 +1,135 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationDeleteAccount.h" + +#import "FUIAccountSettingsOperation_Internal.h" +#import "FUIAccountSettingsOperationForgotPassword.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperationDeleteAccount + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeDeleteAccount; +} + +- (void)execute:(BOOL)showDialog { + if (showDialog) { + [self showDeleteAccountDialog]; + } else { + [self showDeleteAccountViewWithPassword]; + } +} + +- (void)showDeleteAccountDialog { + [self showSelectProviderDialogWithAlertTitle: + FUILocalizedString(kStr_DeleteAccountConfirmationTitle) + alertMessage:FUILocalizedString(kStr_DeleteAccountBody) + alertCloseButton:FUILocalizedString(kStr_Cancel) + providerHandler:^(id provider) { + if (![provider.providerID isEqualToString:FIREmailAuthProviderID]) { + [self reauthenticateWithProvider:provider.providerID actionHandler:^{ + [self showDeleteAccountView]; + }]; + } else { + [self showDeleteAccountViewWithPassword]; + } + }]; +} + +- (void)showDeleteAccountViewWithPassword { + __block FUIStaticContentTableViewCell *passwordCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Password) + value:nil + placeholder:FUILocalizedString(kStr_PlaceholderEnterPassword) + type:FUIStaticContentTableViewCellTypePassword + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil cells:@[passwordCell]], + ]]; + + NSString *message = FUILocalizedString(kStr_DeleteAccountConfirmationMessage); + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] + initWithContents:contents + nextTitle:FUILocalizedString(kStr_Delete) + nextAction:^{ [self deleteCurrentAccountWithPassword:passwordCell.value]; } + headerText:message + footerText:FUILocalizedString(kStr_ForgotPassword) + footerAction:^{ + [FUIAccountSettingsOperationForgotPassword executeOperationWithDelegate:self.delegate]; + }]; + controller.title = FUILocalizedString(kStr_DeleteAccountControllerTitle); + [self.delegate pushViewController:controller]; +} + +- (void)showDeleteAccountView { + NSString *message = FUILocalizedString(kStr_DeleteAccountConfirmationMessage); + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:nil + nextTitle:FUILocalizedString(kStr_Delete) + nextAction:^{ + [self onDeleteAccountViewNextAction]; + } + headerText:message]; + controller.title = FUILocalizedString(kStr_DeleteAccountControllerTitle); + [self.delegate pushViewController:controller]; + +} + +- (void)onDeleteAccountViewNextAction { + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:FUILocalizedString(kStr_DeleteAccountConfirmationTitle) + message:FUILocalizedString(kStr_ActionCantBeUndone) + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *deleteAction = + [UIAlertAction actionWithTitle:FUILocalizedString(kStr_DeleteAccountControllerTitle) + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { + [self deleteCurrentAccount]; + }]; + UIAlertAction *action = + [UIAlertAction actionWithTitle:FUILocalizedString(kStr_Cancel) + style:UIAlertActionStyleCancel + handler:nil]; + [alertController addAction:deleteAction]; + [alertController addAction:action]; + [self.delegate presentViewController:alertController]; + +} + +- (void)deleteCurrentAccountWithPassword:(NSString *)password { + [self reauthenticateWithPassword:password actionHandler:^{ + [self deleteCurrentAccount]; + }]; +} + +- (void)deleteCurrentAccount { + [self.delegate incrementActivity]; + [self.delegate.auth.currentUser deleteWithCompletion:^(NSError *_Nullable error) { + [self.delegate decrementActivity]; + [self finishOperationWithError:error]; + if (!error) { + [self.delegate presentBaseController]; + } + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.h new file mode 100644 index 00000000..50143ffb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationForgotPassword + @brief Handles logic of 'forgot password' operation. + */ +@interface FUIAccountSettingsOperationForgotPassword : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate:showDialog: + @brief Instead use @c executeOperationWithDelegate: + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.m new file mode 100644 index 00000000..4b829b85 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.m @@ -0,0 +1,93 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationForgotPassword.h" + +#import "FUIAccountSettingsOperation_Internal.h" +#import "FUIAuthBaseViewController_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperationForgotPassword + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeForgotPassword; +} + +- (void)execute:(BOOL)showDialog { + [self onForgotPassword]; +} + +- (void)onForgotPassword { + __block FUIStaticContentTableViewCell *inputCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Email) + value:self.delegate.auth.currentUser.email + placeholder:FUILocalizedString(kStr_PlaceholderEnterEmail) + type:FUIStaticContentTableViewCellTypeInput + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent + contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[inputCell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] + initWithContents:contents + nextTitle:FUILocalizedString(kStr_Send) + nextAction:^{ [self onPasswordRecovery:inputCell.value]; } + headerText:FUILocalizedString(kStr_PasswordRecoveryMessage)]; + controller.title = FUILocalizedString(kStr_PasswordRecoveryTitle); + [self.delegate pushViewController:controller]; +} + +- (void)onPasswordRecovery:(NSString *)email { + if (![[FUIAuthBaseViewController class] isValidEmail:email]) { + [self showAlertWithMessage:FUILocalizedString(kStr_InvalidEmailError)]; + return; + } + + [self.delegate incrementActivity]; + + [self.delegate.auth sendPasswordResetWithEmail:email + completion:^(NSError *_Nullable error) { + [self.delegate decrementActivity]; + + if (error) { + [self finishOperationWithError:error]; + return; + } + + NSString *message = [NSString stringWithFormat: + FUILocalizedString(kStr_PasswordRecoveryEmailSentMessage), email]; + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:nil + message:message + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:FUILocalizedString(kStr_OK) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + [self finishOperationWithError:error]; + }]; + [alertController addAction:okAction]; + [self.delegate presentViewController:alertController]; + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.h new file mode 100644 index 00000000..c059a3da --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationSignOut + @brief Handles logic of signing-out operation. + */ +@interface FUIAccountSettingsOperationSignOut : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate:showDialog: + @brief Instead use @c executeOperationWithDelegate: + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog NS_UNAVAILABLE; +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.m new file mode 100644 index 00000000..9ab3bcf7 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.m @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationSignOut.h" + +#import "FUIAccountSettingsOperation_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperationSignOut + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeSignOut; +} + +- (void)execute:(BOOL)showDialog { + [self signOut]; +} + +- (void)signOut{ + NSError *error; + [self.delegate.authUI signOutWithError:&error]; + [self finishOperationWithError:error]; + if (!error) { + [self.delegate presentBaseController]; + } + +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationType.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationType.h new file mode 100644 index 00000000..796d110f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationType.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** @typedef FUIAccountSettingsOperationType + @brief List of all possible Account management operations. + */ +typedef NS_ENUM(NSInteger, FUIAccountSettingsOperationType) { + FUIAccountSettingsOperationTypeUnsupported = 0, + FUIAccountSettingsOperationTypeUpdateName, + FUIAccountSettingsOperationTypeUpdatePassword, + FUIAccountSettingsOperationTypeForgotPassword, + FUIAccountSettingsOperationTypeUpdateEmail, + FUIAccountSettingsOperationTypeUnlinkAccount, + FUIAccountSettingsOperationTypeSignOut, + FUIAccountSettingsOperationTypeDeleteAccount, +}; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.h new file mode 100644 index 00000000..cec0d253 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +@protocol FIRUserInfo; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationUnlinkAccount + @brief Handles logic of unlinking from 3P provider operation. + */ +@interface FUIAccountSettingsOperationUnlinkAccount : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate:showDialog: + @brief Instead use @c executeOperationWithDelegate:showDialog:provider: + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog NS_UNAVAILABLE; + +/** @fn executeOperationWithDelegate: + @brief Instead use @c executeOperationWithDelegate:showDialog:provider: + @param delegate UI delegate which handles all UI related logic. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + NS_UNAVAILABLE; + +/** @fn executeOperationWithDelegate:showDialog:provider: + @brief Creates new instance of @c FUIAccountSettingsOperationUnlinkAccount and executes logic + associated with it. + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @param provider Instance of 3P provider retrieved from currently logged in @c FIRUser. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog + provider:(id)provider; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.m new file mode 100644 index 00000000..7539fd2e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.m @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationUnlinkAccount.h" + +#import "FUIAccountSettingsOperation_Internal.h" +#import "FUIAuthBaseViewController_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FUIAccountSettingsOperationUnlinkAccount () +{ + id _provider; +} +@end + +@implementation FUIAccountSettingsOperationUnlinkAccount + ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog + provider:(id)provider { + FUIAccountSettingsOperationUnlinkAccount *operation = + [[self alloc] initWithDelegate:delegate provider:provider]; + [operation execute:showDialog]; + return operation; +} + +- (instancetype)initWithDelegate:(id)delegate + provider:(id) provider { + if (self = [super initWithDelegate:delegate]) { + _provider = provider; + } + return self; +} + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeUnlinkAccount; +} + +- (void)execute:(BOOL)showDialog { + __block FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle: + [FUIAuthBaseViewController providerLocalizedName:_provider.providerID] + value:_provider.displayName + type:FUIStaticContentTableViewCellTypeDefault + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[cell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:contents + nextTitle: + FUILocalizedString(kStr_UnlinkAction) + nextAction:^{ + [self showUnlinkConfirmationDialog]; + }]; + controller.title = FUILocalizedString(kStr_UnlinkTitle); + [self.delegate pushViewController:controller]; +} + +- (void)showUnlinkConfirmationDialog { + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:FUILocalizedString(kStr_UnlinkConfirmationTitle) + message:FUILocalizedString(kStr_UnlinkConfirmationMessage) + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *action = + [UIAlertAction actionWithTitle:FUILocalizedString(kStr_UnlinkConfirmationActionTitle) + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *_Nonnull action) { [self unlinkAcount]; }]; + [alertController addAction:action]; + UIAlertAction *cancelAction = + [UIAlertAction actionWithTitle:FUILocalizedString(kStr_Cancel) + style:UIAlertActionStyleCancel + handler:nil]; + [alertController addAction:cancelAction]; + [self.delegate presentViewController:alertController]; +} + +- (void)unlinkAcount { + [self.delegate.auth.currentUser unlinkFromProvider:_provider.providerID + completion:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + [self finishOperationWithError:error]; + [self.delegate presentBaseController]; + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.h new file mode 100644 index 00000000..67c55776 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationUpdateEmail + @brief Handles logic of updating email operation. + */ +@interface FUIAccountSettingsOperationUpdateEmail : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate:showDialog: + @brief Instead use @c executeOperationWithDelegate: + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.m new file mode 100644 index 00000000..989ee2ca --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.m @@ -0,0 +1,92 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationUpdateEmail.h" + +#import "FUIAccountSettingsOperation_Internal.h" +#import "FUIAuthBaseViewController_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperationUpdateEmail + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeUpdateEmail; +} + +- (void)execute:(BOOL)showDialog { + if (showDialog) { + [self showUpdateEmailDialog]; + } else { + [self showUpdateEmailView]; + } +} + +- (void)showUpdateEmailDialog { + NSString *message; + message = FUILocalizedString(kStr_UpdateEmailAlertMessage); + [self showVerifyDialogWithMessage:message providerHandler:^{ [self showUpdateEmail]; }]; + +} + +- (void)showUpdateEmailView { + [self showVerifyPasswordViewWithMessage: + FUILocalizedString(kStr_UpdateEmailVerificationAlertMessage) + providerHandler:^{ [self showUpdateEmail]; }]; +} + +- (void)showUpdateEmail { + __block FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Email) + value:self.delegate.auth.currentUser.email + placeholder:FUILocalizedString(kStr_PlaceholderEnterEmail) + type:FUIStaticContentTableViewCellTypeInput + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[cell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:contents + nextTitle:FUILocalizedString(kStr_Save) + nextAction:^{ + [self updateEmailForCurrentUser:cell.value]; + }]; + controller.title = FUILocalizedString(kStr_EditEmailTitle); + [self.delegate pushViewController:controller]; + +} + +- (void)updateEmailForCurrentUser:(NSString *)email { + if (![[FUIAuthBaseViewController class] isValidEmail:email]) { + [self showAlertWithMessage:FUILocalizedString(kStr_InvalidEmailError)]; + } else { + [self.delegate incrementActivity]; + [self.delegate.auth.currentUser updateEmail:email completion:^(NSError *_Nullable error) { + [self.delegate decrementActivity]; + [self finishOperationWithError:error]; + if (!error) { + [self.delegate presentBaseController]; + } + }]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.h new file mode 100644 index 00000000..34bf8cf5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationUpdateName + @brief Handles logic of updating name operation. + */ +@interface FUIAccountSettingsOperationUpdateName : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate: + @brief Instead use @c executeOperationWithDelegate:showDialog: + @param delegate UI delegate which handles all UI related logic. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.m new file mode 100644 index 00000000..6daf83d3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.m @@ -0,0 +1,65 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationUpdateName.h" + +#import "FUIAccountSettingsOperation_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIAccountSettingsOperationUpdateName + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeUpdateName; +} + +- (void)execute:(BOOL)showDialog { + __block FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Name) + value:self.delegate.auth.currentUser.displayName + placeholder:FUILocalizedString(kStr_PlaceholderEnterName) + type:FUIStaticContentTableViewCellTypeInput + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[cell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:contents + nextTitle:FUILocalizedString(kStr_Save) + nextAction:^{ + [self onUpdateName:cell.value]; + }]; + controller.title = FUILocalizedString(kStr_EditNameTitle); + [self.delegate pushViewController:controller]; +} + +- (void)onUpdateName:(NSString *)username { + [self.delegate incrementActivity]; + FIRUserProfileChangeRequest *request = [self.delegate.auth.currentUser profileChangeRequest]; + request.displayName = username; + [request commitChangesWithCompletion:^(NSError *_Nullable error) { + [self.delegate decrementActivity]; + [self finishOperationWithError:error]; + [self.delegate presentBaseController]; + }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.h new file mode 100644 index 00000000..644d5cca --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsOperationUpdatePassword + @brief Handles logic of updating password operation. + */ +@interface FUIAccountSettingsOperationUpdatePassword : FUIAccountSettingsOperation + +/** @fn executeOperationWithDelegate:showDialog: + @brief Instead use @c executeOperationWithDelegate:showDialog:newPassword: + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog NS_UNAVAILABLE; + +/** @fn executeOperationWithDelegate: + @brief Instead use @c executeOperationWithDelegate:showDialog:newPassword: + @param delegate UI delegate which handles all UI related logic. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + NS_UNAVAILABLE; + +/** @fn executeOperationWithDelegate:showDialog:newPassword: + @brief Creates new instance of @c FUIAccountSettingsOperationUnlinkAccount and executes logic + associated with it. + @param delegate UI delegate which handles all UI related logic. + @param showDialog Determines if operation specific UI should be started with confirmation + dialog. + @param newPassword Defines if this is add password (pass YES) or update password operation. + @return Instance of the executed operation. + */ ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog + newPassword:(BOOL)newPassword; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.m new file mode 100644 index 00000000..38beda77 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.m @@ -0,0 +1,126 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperationUpdatePassword.h" + +#import "FUIAccountSettingsOperation_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FUIAccountSettingsOperationUpdatePassword () +{ + BOOL _newPassword; +} +@end + +@implementation FUIAccountSettingsOperationUpdatePassword + ++ (instancetype)executeOperationWithDelegate:(id)delegate + showDialog:(BOOL)showDialog + newPassword:(BOOL)newPassword { + FUIAccountSettingsOperationUpdatePassword *operation = + [[self alloc] initWithDelegate:delegate newPassword:newPassword]; + [operation execute:showDialog]; + return operation; +} + +- (instancetype)initWithDelegate:(id)delegate + newPassword:(BOOL)newPassword { + if (self = [super initWithDelegate:delegate]) { + _newPassword = newPassword; + } + return self; +} + +- (FUIAccountSettingsOperationType)operationType { + return FUIAccountSettingsOperationTypeUpdatePassword; +} + +- (void)execute:(BOOL)showDialog { + if (showDialog) { + [self showUpdatePasswordDialog:_newPassword]; + } else { + [self showUpdatePasswordView]; + } +} + +- (void)showUpdatePasswordDialog:(BOOL)newPassword { + NSString *message; + if (newPassword) { + message = FUILocalizedString(kStr_AddPasswordAlertMessage); + } else { + message = FUILocalizedString(kStr_EditPasswordAlertMessage); + } + + [self showVerifyDialogWithMessage:message + providerHandler:^{ [self showUpdatePassword:newPassword]; }]; + +} + +- (void)showUpdatePasswordView { + [self showVerifyPasswordViewWithMessage: + FUILocalizedString(kStr_ReauthenticateEditPasswordAlertMessage) + providerHandler:^{ [self showUpdatePassword:NO]; }]; +} + +- (void)showUpdatePassword:(BOOL)newPassword { + NSString *placeHolder = newPassword ? FUILocalizedString(kStr_PlaceholderChosePassword) : + FUILocalizedString(kStr_PlaceholderNewPassword); + __block FUIStaticContentTableViewCell *passwordCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_Password) + value:nil + placeholder:placeHolder + type:FUIStaticContentTableViewCellTypePassword + action:nil]; + FUIStaticContentTableViewContent *contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle:nil + cells:@[passwordCell]], + ]]; + + UIViewController *controller = + [[FUIStaticContentTableViewController alloc] initWithContents:contents + nextTitle:FUILocalizedString(kStr_Save) + nextAction:^{ + [self updatePasswordForCurrentUser:passwordCell.value]; + }]; + if (newPassword) { + controller.title = FUILocalizedString(kStr_AddPasswordTitle); + } else { + controller.title = FUILocalizedString(kStr_EditPasswordTitle); + } + [self.delegate pushViewController:controller]; + +} + +- (void)updatePasswordForCurrentUser:(NSString *)password { + if (!password.length) { + [self showAlertWithMessage:FUILocalizedString(kStr_WeakPasswordError)]; + } else { + [self.delegate incrementActivity]; + [self.delegate.auth.currentUser updatePassword:password completion:^(NSError *_Nullable error) { + [self.delegate decrementActivity]; + [self finishOperationWithError:error]; + if (!error) { + [self.delegate presentBaseController]; + } + }]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation_Internal.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation_Internal.h new file mode 100644 index 00000000..fe42c86c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation_Internal.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsOperation.h" + +#import + +#import "FUIAccountSettingsOperationType.h" +#import "FUIAuthStrings.h" +#import "FUIAuth_Internal.h" +#import "FUIStaticContentTableViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FUIAccountSettingsChooseProviderHandler + @brief The type of block invoked when a select provider dialog button is tapped. + */ +typedef void(^FUIAccountSettingsChooseProviderHandler)(id provider); + +/** @typedef FUIAccountSettingsReauthenticateHandler + @brief The type of block invoked when reathentication operation is finished. + */ +typedef void(^FUIAccountSettingsReauthenticateHandler)(void); + +/** Internal methods which are not exposed for public usage. */ +@interface FUIAccountSettingsOperation () + +/** @fn initWithDelegate: + @brief Creates new instance of @c FUIAccountSettingsOperation. + */ +- (instancetype)initWithDelegate:(id)delegate; + +/** @fn finishOperationWithError: + @brief Callback which is used for notification of operation result. + */ +- (void)finishOperationWithError:(nullable NSError *)error; + +/** @fn reauthenticateWithProvider:actionHandler: + @brief Reauthenticates currently logged-in user with specified 3P porviderID. + @param providerID The ID of third party provider. + @param handler Block which is called when user was re-authenticated. + */ +- (void)reauthenticateWithProvider:(NSString *)providerID + actionHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler; + +/** @fn reauthenticateWithPassword:actionHandler: + @brief Reauthenticates currently logged-in user with 'password' auth provider. + @param password Value of the password used for re-authentication of currently loggen-in user. + @param handler Block which is called when user was re-authenticated. + */ +- (void)reauthenticateWithPassword:(NSString *)password + actionHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler; + +/** @fn showSelectProviderDialogWithAlertTitle:alertMessage:alertCloseButton:providerHandler: + @brief Displays alert dialog with all available 3P providers. + @param title The title of the dialog + @param message The message displayed in the alert body. + @param closeActionTitle The title of the close button. + @param handler Block which is called when user selects any of 3P providers. + */ +- (void)showSelectProviderDialogWithAlertTitle:(nullable NSString *)title + alertMessage:(nullable NSString *)message + alertCloseButton:(nullable NSString *)closeActionTitle + providerHandler:(nullable FUIAccountSettingsChooseProviderHandler) + handler; + +/** @fn showVerifyDialogWithMessage:providerHandler: + @brief Displays alert dialog when user need to verify it's identity. + @param message The message displayed in the alert body. + @param handler Block which is called when user selects any of 3P providers. + */ +- (void)showVerifyDialogWithMessage:(NSString *)message + providerHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler; + +/** @fn showVerifyPasswordViewWithMessage:providerHandler: + @brief Displays view with password input field when user need to verify it's identity. + @param message The message displayed in the alert body. + @param handler Block which is called when user selects any of 3P providers. + */ +- (void)showVerifyPasswordViewWithMessage:(NSString *)message + providerHandler:(nullable FUIAccountSettingsReauthenticateHandler)handler; + +/** @fn showAlertWithMessage:message: + @brief Displays alert view with with specified message and OK button. + @param message The message displayed in the alert body. + */ +- (void)showAlertWithMessage:(NSString *)message; + +/** @property delegate + @brief The operation UI delegate which handles all UI callbacks. + */ +@property(nonatomic, weak, readonly) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.h new file mode 100644 index 00000000..472ebb38 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAccountSettingsViewController + @brief Represents View Controller for Account Management UI. This controller should be embedded + in @c UINavigationController in order to present it's internal views. + */ +@interface FUIAccountSettingsViewController : FUIAuthBaseViewController + +/** @property deleteAccountActionDisabled + @brief Whether to hide "Delete account" button, defaults to NO. + */ +@property(nonatomic, assign, getter=isDeleteAccountActionDisabled) + BOOL deleteAccountActionDisabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.m new file mode 100644 index 00000000..d17aae9b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.m @@ -0,0 +1,431 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAccountSettingsViewController.h" + +#import + +#import "FUIAccountSettingsOperation.h" +#import "FUIAccountSettingsOperationDeleteAccount.h" +#import "FUIAccountSettingsOperationForgotPassword.h" +#import "FUIAccountSettingsOperationSignOut.h" +#import "FUIAccountSettingsOperationUnlinkAccount.h" +#import "FUIAccountSettingsOperationUpdateEmail.h" +#import "FUIAccountSettingsOperationUpdateName.h" +#import "FUIAccountSettingsOperationUpdatePassword.h" +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthStrings.h" +#import "FUIStaticContentTableViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var FUIASAccountState + @brief Defines all possible states of current loogged-in @c FIRUser. + */ +typedef NS_ENUM(NSInteger, FUIASAccountState) { + FUIASAccountStateUnknown = 0, + FUIASAccountStateEmailPassword, + FUIASAccountStateLinkedAccountWithEmail, + FUIASAccountStateLinkedAccountWithoutEmail, + FUIASAccountStateLinkedAccountWithEmailPassword +}; + +/** @var kUserAccountImage + @brief Name of icon to show default user account. + */ +static NSString *const kUserAccountImage = @"ic_account_circle.png"; + +@interface FUIAccountSettingsViewController () +@end + +@implementation FUIAccountSettingsViewController { + __weak UITableView *_tableView; + FUIStaticContentTableViewManager *_tableViewManager; + FUIASAccountState _accountState; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _tableViewManager = [[FUIStaticContentTableViewManager alloc] init]; + _tableViewManager.tableView = _tableView; + _tableView.dataSource = _tableViewManager; + _tableView.delegate = _tableViewManager; + [self updateUI]; +} + +#pragma mark - Helpers + +- (FUIASAccountState)accountState { + NSArray> *providers = self.auth.currentUser.providerData; + if (!providers || providers.count == 0) { + return FUIASAccountStateUnknown; + } + + BOOL hasPasswordProvider = NO; + BOOL hasEmailInLinkedProvider = NO; + + for (id userInfo in providers) { + if (userInfo.email.length > 0 && + ![userInfo.providerID isEqualToString:FIREmailAuthProviderID]) { + hasEmailInLinkedProvider = YES; + } + + if ([userInfo.providerID isEqualToString:FIREmailAuthProviderID]) { + hasPasswordProvider = YES; + } + } + + if (providers.count == 1 && hasPasswordProvider) { + return FUIASAccountStateEmailPassword; + } else if (!hasPasswordProvider && !hasEmailInLinkedProvider) { + return FUIASAccountStateLinkedAccountWithoutEmail; + } else if (!hasPasswordProvider && hasEmailInLinkedProvider) { + return FUIASAccountStateLinkedAccountWithEmail; + } else if (hasPasswordProvider && hasEmailInLinkedProvider) { + return FUIASAccountStateLinkedAccountWithEmailPassword; + } else if (hasPasswordProvider && !hasEmailInLinkedProvider) { + return FUIASAccountStateLinkedAccountWithEmailPassword; + } + + return FUIASAccountStateUnknown; +} + +- (void)populateTableHeader { + + if (!self.auth.currentUser) { + _tableViewManager.tableView.tableHeaderView = nil; + return; + } + + CGFloat profileHeight = 60; + UIImageView *headerImage = + [[UIImageView alloc] initWithImage:[UIImage imageNamed:kUserAccountImage]]; + headerImage.layer.cornerRadius = profileHeight / 2; + headerImage.clipsToBounds = YES; + UIView *wrapper = [[UIView alloc] init]; + [wrapper addSubview:headerImage]; + headerImage.translatesAutoresizingMaskIntoConstraints = NO; + [headerImage addConstraint: + [NSLayoutConstraint constraintWithItem:headerImage + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:profileHeight]]; + [headerImage addConstraint: + [NSLayoutConstraint constraintWithItem:headerImage + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:profileHeight]]; + [wrapper addConstraint: + [NSLayoutConstraint constraintWithItem:headerImage + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:wrapper + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + [wrapper addConstraint: + [NSLayoutConstraint constraintWithItem:headerImage + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:wrapper + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + _tableViewManager.tableView.tableHeaderView = wrapper; + CGRect frame = _tableViewManager.tableView.tableHeaderView.frame; + frame.size.height = 90; + _tableViewManager.tableView.tableHeaderView.frame = frame; + + NSURL *photoURL = self.auth.currentUser.photoURL; + if (photoURL) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSData *imageData = [NSData dataWithContentsOfURL:photoURL]; + UIImage *image = [UIImage imageWithData:imageData]; + dispatch_async(dispatch_get_main_queue(), ^{ + headerImage.image = image; + }); + }); + + } +} + +- (void)updateTable { + switch (_accountState) { + case FUIASAccountStateEmailPassword: + [self updateTableStateEmailPassword]; + break; + case FUIASAccountStateLinkedAccountWithEmail: + [self updateTableStateLinkedAccountWithEmail]; + break; + case FUIASAccountStateLinkedAccountWithoutEmail: + [self updateTableStateLinkedAccountWithoutEmail]; + break; + case FUIASAccountStateLinkedAccountWithEmailPassword: + [self updateTableStateLinkedAccountWithEmailPassword]; + break; + + default: + _tableViewManager.contents = nil; + break; + } +} + +- (void)updateTableStateEmailPassword { + _tableViewManager.contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleProfile) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellName) + value:self.auth.currentUser.displayName + action:^{ + [FUIAccountSettingsOperationUpdateName executeOperationWithDelegate:self showDialog:NO]; + }], + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellEmail) + value:self.auth.currentUser.email + action:^{ + [FUIAccountSettingsOperationUpdateEmail executeOperationWithDelegate:self]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleSecurity) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellChangePassword) + action:^{ + [FUIAccountSettingsOperationUpdatePassword executeOperationWithDelegate:self + showDialog:YES + newPassword:NO]; + }] + ]], + [self createActionsSection] + ]]; +} + +- (void)updateTableStateLinkedAccountWithoutEmail { + NSMutableArray *linkedAccounts = + [[NSMutableArray alloc] initWithCapacity:self.auth.currentUser.providerData.count]; + for (id userInfo in self.auth.currentUser.providerData) { + if ([userInfo.providerID isEqualToString:FIREmailAuthProviderID]) { + continue; + } + FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle: + [FUIAuthBaseViewController providerLocalizedName:userInfo.providerID] + value:userInfo.displayName]; + [linkedAccounts addObject:cell]; + } + + _tableViewManager.contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleProfile) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellName) + value:self.auth.currentUser.displayName + action:^{ + [FUIAccountSettingsOperationUpdateName executeOperationWithDelegate:self showDialog:NO]; + }], + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellEmail) + value:self.auth.currentUser.email + action:^{ + [FUIAccountSettingsOperationUpdateEmail executeOperationWithDelegate:self]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleLinkedAccounts) + cells:linkedAccounts], + [self createActionsSection] + ]]; +} + +- (void)updateTableStateLinkedAccountWithEmail { + NSMutableArray *linkedAccounts = + [[NSMutableArray alloc] initWithCapacity:self.auth.currentUser.providerData.count]; + for (id userInfo in self.auth.currentUser.providerData) { + if ([userInfo.providerID isEqualToString:FIREmailAuthProviderID]) { + continue; + } + FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle: + [FUIAuthBaseViewController providerLocalizedName:userInfo.providerID] + value:userInfo.displayName]; + [linkedAccounts addObject:cell]; + } + + _tableViewManager.contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleProfile) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellName) + value:self.auth.currentUser.displayName + action:^{ + [FUIAccountSettingsOperationUpdateName executeOperationWithDelegate:self showDialog:NO]; + }], + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellEmail) + value:self.auth.currentUser.email + action:^{ + [FUIAccountSettingsOperationUpdateEmail executeOperationWithDelegate:self]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleSecurity) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellAddPassword) + action:^{ + [FUIAccountSettingsOperationUpdatePassword executeOperationWithDelegate:self + showDialog:YES + newPassword:YES]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleLinkedAccounts) + cells:linkedAccounts], + [self createActionsSection] + ]]; +} + +- (void)updateTableStateLinkedAccountWithEmailPassword { + NSMutableArray *linkedAccounts = + [[NSMutableArray alloc] initWithCapacity:self.auth.currentUser.providerData.count]; + for (id userInfo in self.auth.currentUser.providerData) { + if ([userInfo.providerID isEqualToString:FIREmailAuthProviderID]) { + continue; + } + FUIStaticContentTableViewCell *cell = + [FUIStaticContentTableViewCell cellWithTitle: + [FUIAuthBaseViewController providerLocalizedName:userInfo.providerID] + value:userInfo.displayName + action:^{ + [FUIAccountSettingsOperationUnlinkAccount executeOperationWithDelegate:self + showDialog:NO + provider:userInfo]; + }]; + [linkedAccounts addObject:cell]; + } + + _tableViewManager.contents = + [FUIStaticContentTableViewContent contentWithSections:@[ + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleProfile) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellName) + value:self.auth.currentUser.displayName + action:^{ + [FUIAccountSettingsOperationUpdateName executeOperationWithDelegate:self showDialog:NO]; + }], + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellEmail) + value:self.auth.currentUser.email + action:^{ + [FUIAccountSettingsOperationUpdateEmail executeOperationWithDelegate:self]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleSecurity) + cells:@[ + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellChangePassword) + action:^{ + [FUIAccountSettingsOperationUpdatePassword executeOperationWithDelegate:self + showDialog:YES + newPassword:NO]; + }] + ]], + [FUIStaticContentTableViewSection sectionWithTitle: + FUILocalizedString(kStr_ASSectionTitleLinkedAccounts) + cells:linkedAccounts], + [self createActionsSection] + ]]; +} + +- (FUIStaticContentTableViewSection *)createActionsSection { + FUIStaticContentTableViewCell *signOutCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellSignOut) + type:FUIStaticContentTableViewCellTypeButton + action:^{ + [FUIAccountSettingsOperationSignOut executeOperationWithDelegate:self]; + } +]; + NSMutableArray *cells = [NSMutableArray arrayWithObject:signOutCell]; + if (!_deleteAccountActionDisabled) { + FUIStaticContentTableViewCell *deleteCell = + [FUIStaticContentTableViewCell cellWithTitle:FUILocalizedString(kStr_ASCellDeleteAccount) + type:FUIStaticContentTableViewCellTypeButton + action:^{ + [FUIAccountSettingsOperationDeleteAccount executeOperationWithDelegate:self + showDialog:YES]; + } +]; + [cells addObject:deleteCell]; + } + return [FUIStaticContentTableViewSection sectionWithTitle:nil cells:cells]; +} + +- (void)updateUI { + _accountState = [self accountState]; + [self populateTableHeader]; + [self updateTable]; +} + +- (void)popToRoot { + [self.navigationController popToViewController:self animated:YES]; +} + +#pragma mark - FUIAccountSettingsOperationUIDelegate + +- (void)presentViewController:(UIViewController *)controller { + [self.navigationController presentViewController:controller animated:YES completion:nil]; +} + +- (void)pushViewController:(UIViewController *)controller { + [super pushViewController:controller]; +} + +- (void)presentBaseController { + [self popToRoot]; + [self updateUI]; +} + +- (void)incrementActivity { + UIViewController *controller = self.navigationController.topViewController; + if (controller == self) { + [super incrementActivity]; + } else if ([controller isKindOfClass:[FUIAuthBaseViewController class]]) { + [(FUIAuthBaseViewController *)controller incrementActivity]; + } +} + +- (void)decrementActivity { + UIViewController *controller = self.navigationController.topViewController; + if (controller == self) { + [super decrementActivity]; + } else if ([controller isKindOfClass:[FUIAuthBaseViewController class]]) { + [(FUIAuthBaseViewController *)controller decrementActivity]; + } +} + +- (UIViewController *)presentingController { + return self; +} +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.xib new file mode 100644 index 00000000..e9bf85ff --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.xib @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIInputTableViewCell.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIInputTableViewCell.xib new file mode 100644 index 00000000..872fa477 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIInputTableViewCell.xib @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIPasswordTableViewCell.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIPasswordTableViewCell.xib new file mode 100644 index 00000000..bd8b11c4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/AccountManagement/FUIPasswordTableViewCell.xib @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.h new file mode 100644 index 00000000..db604ea8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.h @@ -0,0 +1,268 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FUIAccountSettingsOperationType.h" +#import "FUIAuthProvider.h" + +@class FIRAuth; +@class FUIAuthPickerViewController; +@class FUIAuth; +@class FIRUser; +@class FUIEmailEntryViewController; +@class FUIPasswordSignInViewController; +@class FUIPasswordSignUpViewController; +@class FUIPasswordRecoveryViewController; +@class FUIPasswordVerificationViewController; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FUIAuthResultCallback + @brief The type of block invoked when sign-in related events complete. + @param user The user signed in, if any. + @param error The error which occurred, if any. + */ +typedef void (^FUIAuthResultCallback)(FIRUser *_Nullable user, NSError *_Nullable error); + +/** @protocol FUIAuthDelegate + @brief A delegate that receives callbacks or provides custom UI for @c FUIAuth. + */ +@protocol FUIAuthDelegate + +@optional + +/** @fn authUI:didSignInWithAuthDataResult:error: + @brief Message sent after the sign in process has completed to report the signed in user or + error encountered. + @param authUI The @c FUIAuth instance sending the message. + @param authDataResult The data result if the sign in attempt was successful. + @param url pass the deep link associated with an email link sign-in completion. It is useful + for the developer to access the state before the sign-in attempt was triggered. + @param error The error that occurred during sign in, if any. + */ +- (void)authUI:(FUIAuth *)authUI + didSignInWithAuthDataResult:(nullable FIRAuthDataResult *)authDataResult + URL:(nullable NSURL *)url + error:(nullable NSError *)error; + +/** @fn authUI:didSignInWithAuthDataResult:error: + @brief Message sent after the sign in process has completed to report the signed in user or + error encountered. + @param authUI The @c FUIAuth instance sending the message. + @param authDataResult The data result if the sign in attempt was successful. + @param error The error that occurred during sign in, if any. + */ +- (void)authUI:(FUIAuth *)authUI + didSignInWithAuthDataResult:(nullable FIRAuthDataResult *)authDataResult + error:(nullable NSError *)error; + +/** @fn authUI:didSignInWithUser:error: + @brief This is deprecated API and will be removed in a future release. + Use @c authUI:didSignInWithAuthDataResult:error: + Both sign in call backs are called (@c authUI:didSignInWithAuthDataResult:error: + and @c authUI:didSignInWithUser:error:). + This message is sent after the sign in process has completed to report the signed in user or + error encountered. + @param authUI The @c FUIAuth instance sending the message. + @param user The signed in user if the sign in attempt was successful. + @param error The error that occurred during sign in, if any. + */ +- (void)authUI:(FUIAuth *)authUI + didSignInWithUser:(nullable FIRUser *)user + error:(nullable NSError *)error +__attribute__((deprecated("Instead use authUI:didSignInWithAuthDataResult:error:"))); + + +/** @fn authUI:didFinishOperation:error: + @brief Message sent after finishing Account Management operation. + @param authUI The @c FUIAuth instance sending the message. + @param operation The operation type that was just completed. + @param error The error that occurred during operation, if any. +*/ +- (void)authUI:(FUIAuth *)authUI + didFinishOperation:(FUIAccountSettingsOperationType)operation + error:(nullable NSError *)error; + +/** @fn authPickerViewControllerForAuthUI: + @brief Sent to the receiver to ask for an instance of @c FUIAuthPickerViewController subclass + to allow UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @return an instance of @c FUIAuthPickerViewController subclass. + */ +- (FUIAuthPickerViewController *)authPickerViewControllerForAuthUI:(FUIAuth *)authUI; + +/** @fn emailEntryViewControllerForAuthUI: + @brief Sent to the receiver to ask for an instance of @c FUIEmailEntryViewController subclass + to allow UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @return an instance of @c FUIEmailEntryViewController subclass. + */ +- (FUIEmailEntryViewController *)emailEntryViewControllerForAuthUI:(FUIAuth *)authUI; + +/** @fn passwordSignInViewControllerForAuthUI:email: + @brief Sent to the receiver to ask for an instance of @c FUIPasswordSignInViewController subclass + to allow sign-in UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @param email The email user is using for sin-in. + @return an instance of @c FUIPasswordSignInViewController subclass. + */ +- (FUIPasswordSignInViewController *)passwordSignInViewControllerForAuthUI:(FUIAuth *)authUI + email:(NSString *)email; + +/** @fn passwordSignInViewControllerForAuthUI:email: + @brief Sent to the receiver to ask for an instance of @c FUIPasswordSignUpViewController subclass + to allow sign-up UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @param email The email user is using for sin-in. + @param requireDisplayName Whether the displayname field is required . + @return an instance of @c FUIPasswordSignUpViewController subclass. + */ +- (FUIPasswordSignUpViewController *)passwordSignUpViewControllerForAuthUI:(FUIAuth *)authUI + email:(NSString *)email + requireDisplayName:(BOOL)requireDisplayName; + +/** @fn passwordRecoveryViewControllerForAuthUI:email: + @brief Sent to the receiver to ask for an instance of @c FUIPasswordRecoveryViewController subclass + to allow sign-up UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @param email The email user is using for password recovery. + @return an instance of @c FUIPasswordRecoveryViewController subclass. + */ +- (FUIPasswordRecoveryViewController *)passwordRecoveryViewControllerForAuthUI:(FUIAuth *)authUI + email:(NSString *)email; + +/** @fn passwordVerificationViewControllerForAuthUI:email:newCredential: + @brief Sent to the receiver to ask for an instance of @c FUIPasswordVerificationViewController subclass + to allow password verification UI customizations. + @param authUI The @c FUIAuth instance sending the message. + @param email The email user is using for sin-in. + @param newCredential This @c FIRAuthCredential obtained from linked account. + @return an instance of @c FUIPasswordVerificationViewController subclass. + */ +- (FUIPasswordVerificationViewController *)passwordVerificationViewControllerForAuthUI:(FUIAuth *)authUI + email:(NSString *)email + newCredential:(FIRAuthCredential *)newCredential; +@end + +/** @class FUIAuth + @brief Provides various iOS UIs for Firebase Auth. + */ +@interface FUIAuth : NSObject + +/** @fn defaultAuthUI + @brief Gets the @c FUIAuth object for the default FirebaseApp. + @remarks Thread safe. + */ ++ (nullable FUIAuth *)defaultAuthUI; + +/** @fn authUIWithAuth: + @brief Gets the @c FUIAuth instance for a @c FIRAuth. + @param auth The @c FIRAuth for which to retrieve the associated @c FUIAuth instance. + @return The @c FUIAuth instance associated with the given @c FIRAuth. + @remarks Thread safe. + */ ++ (nullable FUIAuth *)authUIWithAuth:(FIRAuth *)auth; + +/** @property app + @brief Gets the @c FIRAuth this auth UI object is connected to. + */ +@property(nonatomic, weak, readonly, nullable) FIRAuth *auth; + +/** @property providers + @brief The @c FUIAuthProvider implementations to use for sign-in. + */ +@property(nonatomic, copy) NSArray> *providers; + +/** @property shouldHideCancelButton + @brief Whether to hide the cancel button, defaults to NO. + */ +@property(nonatomic, assign) BOOL shouldHideCancelButton; + +/** @property interactiveDismissEnabled + @brief Whether or not interactive dismiss should be enabled on iOS 13 and above devices. + */ +@property(nonatomic, assign, getter=isInteractiveDismissEnabled) BOOL interactiveDismissEnabled API_AVAILABLE(ios(13)); + +/** @property customStringsBundle + @brief Custom strings bundle supplied by the developer. Nil when there is no custom strings + bundle set. In which case the default bundle will be used. + @remarks Set this property to nil in order to remove the custom strings bundle and revert to + using the default bundle. + */ +@property(nonatomic, strong, nullable) NSBundle *customStringsBundle; + +/** @property TOSURL + @brief The URL of your app's Terms of Service. If not nil, a Terms of Service notice is + displayed on the initial sign-in screen and potentially the phone number auth and + email/password account creation screen. + */ +@property(nonatomic, copy, nullable) NSURL *TOSURL; + +/** @property shouldAutoUpgradeAnonymousUsers + @brief Whether to enable auto upgrading of anonymous accounts, defaults to NO. + */ +@property(nonatomic, assign, getter=shouldAutoUpgradeAnonymousUsers) BOOL autoUpgradeAnonymousUsers; + +/** @property privacyPolicyURL + @brief The URL of your app's Privacy Policy. If not nil, a privacy policy notice is + displayed on the initial sign-in screen and potentially the phone number auth and + email/password account creation screen. + */ +@property(nonatomic, copy, nullable) NSURL *privacyPolicyURL; + +/** @property delegate + @brief A delegate that receives callbacks or provides custom UI for @c FUIAuth. + */ +@property(nonatomic, weak) id delegate; + +/** @fn init + @brief Please use @c FUIAuth.authUIWithAuth to get a @c FUIAuth instance. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn handleOpenURL: + @brief Should be called from your @c UIApplicationDelegate in + @c UIApplicationDelegate.application:openURL:options: to finish sign-in flows. + @param URL The URL which may be handled by Firebase Auth UI if an URL is expected. + @param sourceApplication The application which tried opening the URL. + @return YES if Firebase Auth UI handled the URL. NO otherwise. + */ +- (BOOL)handleOpenURL:(NSURL *)URL + sourceApplication:(nullable NSString *)sourceApplication; + +/** @fn authViewController + @brief Returns an instance of the initial navigation view controller of AuthUI. + @return An instance of the the initial navigation view controller of AuthUI. + */ +- (UINavigationController *)authViewController; + +/** @fn signOutWithError: + @brief Signs out the current user from Firebase and all providers. + @param error Optionally; if an error occurs during Firebase sign out, upon return contains an + NSError object that describes the problem; is nil otherwise. If Firebase error occurs all + providers are not logged-out and sign-out should be retried. + @return @YES when the sign out request was successful. @NO otherwise. + @remarks Possible error codes: + - @c FIRAuthErrorCodeKeychainError Indicates an error occurred when accessing the keychain. + The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo dictionary + will contain more information about the error encountered. + */ +- (BOOL)signOutWithError:(NSError *_Nullable *_Nullable)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.m new file mode 100644 index 00000000..5ab32ff5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth.m @@ -0,0 +1,417 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuth_Internal.h" + +#import + +#import +#import +#import +#import +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthErrors.h" +#import "FUIAuthErrorUtils.h" +#import "FUIAuthPickerViewController.h" +#import "FUIAuthStrings.h" + +/** @var kAppNameCodingKey + @brief The key used to encode the app Name for NSCoding. + */ +static NSString *const kAppNameCodingKey = @"appName"; + +/** @var kAuthAssociationKey + @brief The address of this variable is used as the key for associating FUIAuth instances with + root FIRAuth objects. + */ +static const char kAuthAssociationKey; + +/** @var kErrorUserInfoEmailKey + @brief The key for the email address in the userInfo dictionary of a sign in error. + */ +static NSString *const kErrorUserInfoEmailKey = @"FIRAuthErrorUserInfoEmailKey"; + +/** @var kFirebaseAuthUIFrameworkMarker + @brief The marker in the HTTP header that indicates the presence of Firebase Auth UI. + */ +static NSString *const kFirebaseAuthUIFrameworkMarker = @"FirebaseUI-iOS"; + +/** @category FIRAuth(InternalInterface) + @brief Redeclares the internal interface not publicly exposed in FIRAuth. + */ +@interface FIRAuth (InternalInterface) + +/** @property additionalFrameworkMarker + @brief Additional framework marker that will be added as part of the header of every request. + */ +@property(nonatomic, copy, nullable) NSString *additionalFrameworkMarker; + +@end + +@interface FUIAuth () + +/** @fn initWithAuth: + @brief auth The @c FIRAuth to associate the @c FUIAuth instance with. + */ +- (instancetype)initWithAuth:(FIRAuth *)auth NS_DESIGNATED_INITIALIZER; + +@end + +@implementation FUIAuth { + id __weak _emailAuthProvider; +} + ++ (nullable FUIAuth *)defaultAuthUI { + FIRAuth *defaultAuth = [FIRAuth auth]; + if (!defaultAuth) { + return nil; + } + return [self authUIWithAuth:defaultAuth]; +} + ++ (nullable FUIAuth *)authUIWithAuth:(FIRAuth *)auth { + NSParameterAssert(auth != nil); + @synchronized (self) { + // Let the FIRAuth instance retain the FUIAuth instance. + FUIAuth *authUI = objc_getAssociatedObject(auth, &kAuthAssociationKey); + if (!authUI) { + authUI = [[FUIAuth alloc] initWithAuth:auth]; + objc_setAssociatedObject(auth, &kAuthAssociationKey, authUI, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + if ([auth respondsToSelector:@selector(setAdditionalFrameworkMarker:)]) { + auth.additionalFrameworkMarker = kFirebaseAuthUIFrameworkMarker; + } + // Update auth with the actual language used in the app. + // If localization is not provided by developer, the first localization available, + // ordered by the user's preferred order, is used. + auth.languageCode = [NSBundle mainBundle].preferredLocalizations.firstObject; + } + return authUI; + } +} + +- (instancetype)initWithAuth:(FIRAuth *)auth { + self = [super init]; + if (self) { + _auth = auth; + _interactiveDismissEnabled = YES; + } + return self; +} + +- (BOOL)handleOpenURL:(NSURL *)URL + sourceApplication:(NSString *)sourceApplication { + // Complete IDP-based sign-in flow. + for (id provider in _providers) { + if ([provider handleOpenURL:URL sourceApplication:sourceApplication]) { + return YES; + } + } + // The URL was not meant for us. + return NO; +} + +- (UINavigationController *)authViewController { + static UINavigationController *authViewController; + + UIViewController *controller; + if ([self.delegate respondsToSelector:@selector(authPickerViewControllerForAuthUI:)]) { + controller = [self.delegate authPickerViewControllerForAuthUI:self]; + } else { + controller = [[FUIAuthPickerViewController alloc] initWithAuthUI:self]; + } + authViewController = [[UINavigationController alloc] initWithRootViewController:controller]; + + return authViewController; +} + +- (BOOL)signOutWithError:(NSError *_Nullable *_Nullable)error { + // sign out from Firebase + BOOL success = [self.auth signOut:error]; + if (success) { + // sign out from all providers (wipes provider tokens too) + for (id provider in _providers) { + [provider signOut]; + } + } + + return success; +} + +- (void)signInWithProviderUI:(id)providerUI + presentingViewController:(FUIAuthBaseViewController *)presentingViewController + defaultValue:(nullable NSString *)defaultValue { + + // Sign out first to make sure sign in starts with a clean state. + [providerUI signOut]; + [providerUI signInWithDefaultValue:defaultValue + presentingViewController:presentingViewController + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error, + _Nullable FIRAuthResultCallback result, + NSDictionary *_Nullable userInfo) { + BOOL isAuthPickerShown = + [presentingViewController isKindOfClass:[FUIAuthPickerViewController class]]; + if (error) { + if (!isAuthPickerShown || error.code != FUIAuthErrorCodeUserCancelledSignIn) { + [self invokeResultCallbackWithAuthDataResult:nil URL:nil error:error]; + } + if (result) { + result(nil, error); + } + return; + } + + // Test if it's an anonymous login. + if (self.auth.currentUser.isAnonymous && !credential) { + if (result) { + result(self.auth.currentUser, nil); + } + // Hide Auth Picker Controller which was presented modally. + if (isAuthPickerShown && presentingViewController.presentingViewController) { + [presentingViewController dismissViewControllerAnimated:YES completion:nil]; + } + FIRAuthDataResult *authResult = userInfo[FUIAuthProviderSignInUserInfoKeyAuthDataResult]; + if (authResult != nil) { + [self invokeResultCallbackWithAuthDataResult:authResult URL:nil error:error]; + } + return; + } + + // Check for the presence of an anonymous user and whether automatic upgrade is enabled. + if (self.auth.currentUser.isAnonymous && self.shouldAutoUpgradeAnonymousUsers) { + [self autoUpgradeAccountWithProviderUI:providerUI + presentingViewController:presentingViewController + credential:credential + resultCallback:result]; + } else { + [self.auth signInWithCredential:credential + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + if (error && error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) { + NSString *email = error.userInfo[kErrorUserInfoEmailKey]; + [self.emailAuthProvider handleAccountLinkingForEmail:email + newCredential:credential + presentingViewController:presentingViewController + signInResult:result]; + + return; + } + if (error) { + if (result) { + result(nil, error); + } + [self invokeResultCallbackWithAuthDataResult:nil URL:nil error:error]; + return; + } + [self completeSignInWithResult:authResult + error:nil + presentingViewController:presentingViewController + callback:result]; + }]; + } + }]; +} + +- (void)autoUpgradeAccountWithProviderUI:(id)providerUI + presentingViewController:(FUIAuthBaseViewController *)presentingViewController + credential:(nullable FIRAuthCredential *)credential + resultCallback:(nullable FIRAuthResultCallback)callback { + [self.auth.currentUser + linkWithCredential:credential + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError * _Nullable error) { + if (error) { + // Check for "credential in use" conflict error and handle appropriately. + if (error.code == FIRAuthErrorCodeCredentialAlreadyInUse) { + FIRAuthCredential *newCredential = error.userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey]; + NSDictionary *userInfo = @{ }; + if (newCredential) { + userInfo = @{ FUIAuthCredentialKey : newCredential }; + } + NSError *mergeError = [FUIAuthErrorUtils mergeConflictErrorWithUserInfo:userInfo + underlyingError:error]; + [self completeSignInWithResult:authResult + error:mergeError + presentingViewController:presentingViewController + callback:callback]; + } else if (error.code == FIRAuthErrorCodeEmailAlreadyInUse) { + if ([providerUI respondsToSelector:@selector(email)]) { + // Link federated providers + [self.emailAuthProvider signInWithEmailHint:[providerUI email] + presentingViewController:presentingViewController + originalError:error + completion: + ^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable emailError, + FIRAuthCredential *_Nullable existingCredential) { + if (emailError) { + [self completeSignInWithResult:nil + error:emailError + presentingViewController:presentingViewController + callback:callback]; + return; + } + + if (![authResult.user.email isEqualToString:[providerUI email]] + && credential) { + NSDictionary *userInfo = @{ + FUIAuthCredentialKey : credential, + }; + NSError *mergeError = [FUIAuthErrorUtils mergeConflictErrorWithUserInfo:userInfo + underlyingError:error]; + [self completeSignInWithResult:authResult + error:mergeError + presentingViewController:presentingViewController + callback:callback]; + return; + } + + [authResult.user linkWithCredential:credential + completion:^(FIRAuthDataResult *authResult, + NSError *linkError) { + if (linkError) { + [self completeSignInWithResult:nil + error:linkError + presentingViewController:presentingViewController + callback:callback]; + return; + } + FIRAuthCredential *newCredential = credential; + NSDictionary *userInfo = @{ + FUIAuthCredentialKey : newCredential, + }; + NSError *mergeError = [FUIAuthErrorUtils mergeConflictErrorWithUserInfo:userInfo + underlyingError:error]; + [self completeSignInWithResult:authResult + error:mergeError + presentingViewController:presentingViewController + callback:callback]; + }]; + }]; + } + } else { + [self completeSignInWithResult:nil + error:error + presentingViewController:presentingViewController + callback:callback]; + } + } else { + [self completeSignInWithResult:authResult + error:nil + presentingViewController:presentingViewController + callback:callback]; + } + }]; +} + +- (void)completeSignInWithResult:(nullable FIRAuthDataResult *)authResult + error:(nullable NSError *)error + presentingViewController:(FUIAuthBaseViewController *)presentingViewController + callback:(nullable FIRAuthResultCallback)callback { + BOOL isAuthPickerShown = + [presentingViewController isKindOfClass:[FUIAuthPickerViewController class]]; + if (callback) { + callback(authResult.user, error); + } + // Hide Auth Picker Controller which was presented modally. + if (isAuthPickerShown && presentingViewController.presentingViewController) { + [presentingViewController dismissViewControllerAnimated:YES completion:^{ + [self invokeResultCallbackWithAuthDataResult:authResult URL:nil error:error]; + }]; + } else { + [self invokeResultCallbackWithAuthDataResult:authResult URL:nil error:error]; + } +} + +#pragma mark - Internal Methods + +- (void)invokeResultCallbackWithAuthDataResult:(nullable FIRAuthDataResult *)authDataResult + URL:(nullable NSURL *)url + error:(nullable NSError *)error { + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.delegate respondsToSelector:@selector(authUI:didSignInWithAuthDataResult:URL:error:)]) { + [self.delegate authUI:self + didSignInWithAuthDataResult:authDataResult + URL:url + error:error]; + } + if ([self.delegate respondsToSelector:@selector(authUI:didSignInWithAuthDataResult:error:)]) { + [self.delegate authUI:self didSignInWithAuthDataResult:authDataResult error:error]; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if ([self.delegate respondsToSelector:@selector(authUI:didSignInWithUser:error:)]) { + [self.delegate authUI:self didSignInWithUser:authDataResult.user error:error]; + } +#pragma clang diagnostic pop + }); +} + +- (void)invokeOperationCallback:(FUIAccountSettingsOperationType)operation + error:(NSError *_Nullable)error { + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.delegate respondsToSelector:@selector(authUI:didFinishOperation:error:)]) { + [self.delegate authUI:self didFinishOperation:operation error:error]; + } + }); +} + +- (nullable id)providerWithID:(NSString *)providerID { + NSArray> *providers = self.providers; + for (id provider in providers) { + if ([provider.providerID isEqual:providerID]) { + return provider; + } + } + return nil; +} + +- (void)setEmailAuthProvider:(id)emailAuthProvider { + _emailAuthProvider = emailAuthProvider; +} + +- (id)emailAuthProvider { + return _emailAuthProvider; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + NSString *appName = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAppNameCodingKey]; + if (!appName) { + return nil; + } + FIRApp *app = [FIRApp appNamed:appName]; + if (!app) { + return nil; + } + FIRAuth *auth = [FIRAuth authWithApp:app]; + if (!auth) { + return nil; + } + return [self initWithAuth:auth]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_auth.app.name forKey:kAppNameCodingKey]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.h new file mode 100644 index 00000000..6354c95e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.h @@ -0,0 +1,124 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@class FIRAuth; +@class FUIAuth; +@protocol FUIAuthProvider; + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAuthBaseViewController + @brief The base view controller that provides common methods for all subclasses. + */ +@interface FUIAuthBaseViewController : UIViewController + +/** @typedef FUIAuthAlertActionHandler + @brief The type of block called when an alert view is dismissed by a user action. + */ +typedef void (^FUIAuthAlertActionHandler)(void); + +/** @property auth + @brief The @c FIRAuth instance of the application. + */ +@property(nonatomic, strong, readonly) FIRAuth *auth; + +/** @property authUI + @brief The @c FUIAuth instance of the application. + */ +@property(nonatomic, strong, readonly) FUIAuth *authUI; + +/** @fn init + @brief Please use @c initWithNibName:bundle:authUI:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithStyle: + @brief Please use @c initWithNibName:bundle:authUI:. + */ +- (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; + +/** @fn initWithNibName:bundle: + @brief Please use @c initWithNibName:bundle:authUI:. + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil + bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE; + +/** @fn initWithNibName:bundle:authUI: + @brief Designated initializer. + @param nibNameOrNil The name of the nib file to associate with the view controller. + @param nibBundleOrNil The bundle in which to search for the nib file. + @param authUI The @c FUIAuth instance that manages this view controller. + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil + bundle:(nullable NSBundle *)nibBundleOrNil + authUI:(FUIAuth *)authUI NS_DESIGNATED_INITIALIZER; + +/** @fn initWithAuthUI: + @brief Convenience initializer. If your custom auth picker controller is using its + own nib file, this initializer should be overwritten. + @param authUI The @c FUIAuth instance that manages this view controller. + */ +- (instancetype)initWithAuthUI:(FUIAuth *)authUI; + +/** @fn onBack + @brief Pops the view controller from navigation stack. If current controller is root + works as @c cancelAuthorization + */ +- (void)onBack; + +/** @fn cancelAuthorization + @brief Cancels Authorization flow, calls UI delegate callbacks and hides UI + */ +- (void)cancelAuthorization; + +/** @fn showSignInAlertWithEmail:provider:handler: + @brief Displays an alert asking the user to confirm whether or not they want to proceed with the selected provider. + @param email The email address to sign in with. + @param provider The identity provider to sign in with. + @param signinHandler Handler for the sign in action of the alert. + @param cancelHandler Handler for the cancel action of the alert. + */ ++ (void)showSignInAlertWithEmail:(NSString *)email + provider:(id)provider + presentingViewController:(UIViewController *)presentingViewController + signinHandler:(FUIAuthAlertActionHandler)signinHandler + cancelHandler:(FUIAuthAlertActionHandler)cancelHandler; + +/** @fn incrementActivity + @brief Increment the current activity count. If there's positive number of activities, display + and animate the activity indicator with a short delay. + @remarks Calls to @c incrementActivity and @c decrementActivity should be balanced. + */ +- (void)incrementActivity; + +/** @fn decrementActivity + @brief Decrement the current activity count. If the count reaches 0, stop and hide the + activity indicator. + @remarks Calls to @c incrementActivity and @c decrementActivity should be balanced. + */ +- (void)decrementActivity; + +/** @fn addActivityIndicator: + @brief Creates and adds an activity indicator to the center of the specified view. + @param view The view where indicator is shown. + */ ++ (UIActivityIndicatorView *)addActivityIndicator:(UIView *)view; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.m new file mode 100644 index 00000000..1bba323a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController.m @@ -0,0 +1,448 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthBaseViewController_Internal.h" + +#import +#import "FUIAuthErrorUtils.h" +#import "FUIAuthStrings.h" +#import "FUIAuthUtils.h" +#import "FUIAuth_Internal.h" +#import "objc/runtime.h" + +/** @var kActivityIndiactorPadding + @brief The padding between the activity indiactor and its overlay. + */ +static const CGFloat kActivityIndiactorPadding = 20.0f; + +/** @var kActivityIndiactorOverlayCornerRadius + @brief The corner radius of the overlay of the activity indicator. + */ +static const CGFloat kActivityIndiactorOverlayCornerRadius = 20.0f; + +/** @var kActivityIndiactorOverlayOpacity + @brief The opacity of the overlay of the activity indicator. + */ +static const CGFloat kActivityIndiactorOverlayOpacity = 0.8f; + +/** @var kActivityIndiactorAnimationDelay + @brief The time delay before the activity indicator is actually animated. + */ +static const NSTimeInterval kActivityIndiactorAnimationDelay = 0.5f; + +/** @var kUITableViewCellHeight + @brief Height of all table view cells used in subclasses of the controller. + */ +static const CGFloat kUITableViewCellHeight = 44.f; + +/** @var kEmailRegex + @brief Regular expression for matching email addresses. + */ +static NSString *const kEmailRegex = @".+@([a-zA-Z0-9\\-]+\\.)+[a-zA-Z0-9]{2,63}"; + +/** @var kAuthUICodingKey + @brief The key used to encode @c FUIAuth instance for NSCoding. + */ +static NSString *const kAuthUICodingKey = @"authUI"; + +@implementation FUIAuthBaseViewController { + /** @var _activityIndicator + @brief A spinner that is displayed when there's an ongoing activity. + */ + UIActivityIndicatorView *_activityIndicator; + + /** @var _activityCount + @brief Count of current ongoing activities. + */ + NSInteger _activityCount; +} + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil + bundle:(NSBundle *)nibBundleOrNil + authUI:(FUIAuth *)authUI { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + _auth = authUI.auth; + _authUI = authUI; + + _activityIndicator = [[self class] addActivityIndicator:self.view]; + } + return self; +} + +- (instancetype)initWithAuthUI:(FUIAuth *)authUI { + return [self initWithNibName:NSStringFromClass([self class]) + bundle:[FUIAuthUtils bundleNamed:FUIAuthBundleName] + authUI:authUI]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + CGPoint activityIndicatorCenter = self.view.center; + // Compensate for bounds adjustment if any. + activityIndicatorCenter.y += self.view.bounds.origin.y; + _activityIndicator.center = activityIndicatorCenter; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + FUIAuth *authUI = [aDecoder decodeObjectOfClass:[FUIAuth class] forKey:kAuthUICodingKey]; + if (!authUI) { + return nil; + } + return [self initWithAuthUI:authUI]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_authUI forKey:kAuthUICodingKey]; +} + +#pragma mark - Utilities + ++ (BOOL)isValidEmail:(NSString *)email { + static dispatch_once_t onceToken; + static NSPredicate *emailPredicate; + dispatch_once(&onceToken, ^{ + emailPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", kEmailRegex]; + }); + return [emailPredicate evaluateWithObject:email]; +} + ++ (UIActivityIndicatorView *)addActivityIndicator:(UIView *)view { + if (!view) { + return nil; + } + UIActivityIndicatorView *activityIndicator = + [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + UIView *tintView = [[UIView alloc] initWithFrame:CGRectInset(activityIndicator.frame, + -kActivityIndiactorPadding, + -kActivityIndiactorPadding)]; + tintView.backgroundColor = + [UIColor colorWithWhite:0 alpha:kActivityIndiactorOverlayOpacity]; + tintView.layer.cornerRadius = kActivityIndiactorOverlayCornerRadius; + [activityIndicator addSubview:tintView]; + + // Align tintView (transparent background). + tintView.translatesAutoresizingMaskIntoConstraints = NO; + [activityIndicator addConstraint: + [NSLayoutConstraint constraintWithItem:tintView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:CGRectGetWidth(tintView.frame)]]; + [activityIndicator addConstraint: + [NSLayoutConstraint constraintWithItem:tintView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:activityIndicator + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + [activityIndicator addConstraint: + [NSLayoutConstraint constraintWithItem:tintView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:CGRectGetHeight(tintView.frame)]]; + [activityIndicator addConstraint: + [NSLayoutConstraint constraintWithItem:tintView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:activityIndicator + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + [activityIndicator sendSubviewToBack:tintView]; + + [view addSubview:activityIndicator]; + // Align activity indicator. + activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; + [view addConstraint: + [NSLayoutConstraint constraintWithItem:activityIndicator + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeWidth + multiplier:1 + constant:0]]; + [view addConstraint: + [NSLayoutConstraint constraintWithItem:activityIndicator + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + [view addConstraint: + [NSLayoutConstraint constraintWithItem:activityIndicator + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeHeight + multiplier:1 + constant:0]]; + [view addConstraint: + [NSLayoutConstraint constraintWithItem:activityIndicator + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + return activityIndicator; +} + +- (void)showAlertWithMessage:(NSString *)message { + [[self class] showAlertWithMessage:message presentingViewController:self]; +} + ++ (void)showAlertWithMessage:(NSString *)message { + [[self class] showAlertWithMessage:message presentingViewController:nil]; +} + ++ (void)showAlertWithMessage:(NSString *)message + presentingViewController:(nullable UIViewController *)presentingViewController { + [[self class] showAlertWithTitle:message + message:nil + presentingViewController:presentingViewController]; +} + ++ (void)showAlertWithTitle:(nullable NSString *)title + message:(nullable NSString *)message + presentingViewController:(nullable UIViewController *)presentingViewController { + [[self class] showAlertWithTitle:title + message:message + actionTitle:nil + actionHandler:nil + dismissTitle:FUILocalizedString(kStr_OK) + dismissHandler:nil + presentingViewController:presentingViewController]; +} + ++ (void)showAlertWithTitle:(nullable NSString *)title + message:(nullable NSString *)message + actionTitle:(nullable NSString *)actionTitle + actionHandler:(nullable FUIAuthAlertActionHandler)actionHandler + dismissTitle:(nullable NSString *)dismissTitle + dismissHandler:(nullable FUIAuthAlertActionHandler)dismissHandler + presentingViewController:(nullable UIViewController *)presentingViewController { + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + if (actionTitle) { + UIAlertAction *action = + [UIAlertAction actionWithTitle:actionTitle + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + if (actionHandler) { + actionHandler(); + } + }]; + [alertController addAction:action]; + } + + if (dismissTitle) { + UIAlertAction *dismissAction = + [UIAlertAction actionWithTitle:dismissTitle + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * _Nonnull action) { + if (dismissHandler) { + dismissHandler(); + } + }]; + [alertController addAction:dismissAction]; + } + + if (presentingViewController) { + [presentingViewController presentViewController:alertController animated:YES completion:nil]; + } else { + UIViewController *viewController = [[UIViewController alloc] init]; + viewController.view.backgroundColor = UIColor.clearColor; + UIWindow *window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; + window.rootViewController = viewController; + window.windowLevel = UIWindowLevelAlert + 1; + [window makeKeyAndVisible]; + [viewController presentViewController:alertController animated:YES completion:nil]; + + if (@available(iOS 13.0, *)) { + /* + Earlier iOS versions established a strong reference to the window when makeKeyAndVisible was called. + Now we add one from the alert controller, to prevent objects from getting garbage collected right away. + */ + static char key; + objc_setAssociatedObject(alertController, &key, window, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + } +} + ++ (void)showSignInAlertWithEmail:(NSString *)email + provider:(id)provider + presentingViewController:(UIViewController *)presentingViewController + signinHandler:(FUIAuthAlertActionHandler)signinHandler + cancelHandler:(FUIAuthAlertActionHandler)cancelHandler { + [self showSignInAlertWithEmail:email + providerShortName:provider.shortName + providerSignInLabel:provider.signInLabel + presentingViewController:presentingViewController + signinHandler:signinHandler + cancelHandler:cancelHandler]; +} + ++ (void)showSignInAlertWithEmail:(NSString *)email + providerShortName:(NSString *)providerShortName + providerSignInLabel:(NSString *)providerSignInLabel + presentingViewController:(UIViewController *)presentingViewController + signinHandler:(FUIAuthAlertActionHandler)signinHandler + cancelHandler:(FUIAuthAlertActionHandler)cancelHandler { + NSString *message = + [NSString stringWithFormat:FUILocalizedString(kStr_ProviderUsedPreviouslyMessage), + email, providerShortName]; + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:FUILocalizedString(kStr_ExistingAccountTitle) + message:message + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *signInAction = + [UIAlertAction actionWithTitle:providerSignInLabel + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + if (signinHandler) { + signinHandler(); + } + }]; + [alertController addAction:signInAction]; + UIAlertAction *cancelAction = + [UIAlertAction actionWithTitle:FUILocalizedString(kStr_Cancel) + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * _Nonnull action) { + if (cancelHandler) { + cancelHandler(); + } + }]; + [alertController addAction:cancelAction]; + [presentingViewController presentViewController:alertController animated:YES completion:nil]; +} + +- (void)pushViewController:(UIViewController *)viewController { + [[self class] pushViewController:viewController + navigationController:self.navigationController]; +} + +- (void)dismissNavigationControllerAnimated:(BOOL)animated completion:(void (^)(void))completion { + if (self.navigationController.presentingViewController == nil){ + if (completion){ + completion(); + } + } else { + [self.navigationController dismissViewControllerAnimated:animated completion:completion]; + } +} + ++ (void)pushViewController:(UIViewController *)viewController + navigationController:(UINavigationController *)navigationController { + // Override the back button title with "Back". + viewController.navigationItem.backBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:FUILocalizedString(kStr_Back) + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + [navigationController pushViewController:viewController animated:YES]; +} + + ++ (UIBarButtonItem *)barItemWithTitle:(NSString *)title + target:(nullable id)target + action:(SEL)action { + UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:title + style:UIBarButtonItemStylePlain + target:target + action:action]; + return buttonItem; +} + +- (void)onBack { + if (self.navigationController.viewControllers.count > 1) { + [self.navigationController popViewControllerAnimated:YES]; + } else { + [self cancelAuthorization]; + } +} + +- (void)incrementActivity { + _activityCount++; + + // Delay the display of acitivty indiactor for a short period of time. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(kActivityIndiactorAnimationDelay * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self->_activityIndicator.superview bringSubviewToFront:self->_activityIndicator]; + if (self->_activityCount > 0) { + [self->_activityIndicator startAnimating]; + } + }); +} + +- (void)decrementActivity { + _activityCount--; + + if (_activityCount < 0) { + NSLog(@"Unbalanced calls to incrementActivity and decrementActivity."); + _activityCount = 0; + } + + if (_activityCount == 0) { + [_activityIndicator.superview sendSubviewToBack:_activityIndicator]; + [_activityIndicator stopAnimating]; + } +} + +- (void)cancelAuthorization { + [self dismissNavigationControllerAnimated:YES completion:^{ + NSError *error = [FUIAuthErrorUtils userCancelledSignInError]; + [self.authUI invokeResultCallbackWithAuthDataResult:nil URL:nil error:error]; + }]; +} + ++ (NSString *)providerLocalizedName:(NSString *)providerId { + if ([providerId isEqualToString:FIREmailAuthProviderID]) { + return FUILocalizedString(kStr_ProviderTitlePassword); + } else if ([providerId isEqualToString:FIRGoogleAuthProviderID]) { + return FUILocalizedString(kStr_ProviderTitleGoogle); + } else if ([providerId isEqualToString:FIRFacebookAuthProviderID]) { + return FUILocalizedString(kStr_ProviderTitleFacebook); + } else if ([providerId isEqualToString:FIRTwitterAuthProviderID]) { + return FUILocalizedString(kStr_ProviderTitleTwitter); + } + return @""; +} + +- (void)enableDynamicCellHeightForTableView:(UITableView *)tableView { + tableView.rowHeight = UITableViewAutomaticDimension; + tableView.estimatedRowHeight = kUITableViewCellHeight; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController_Internal.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController_Internal.h new file mode 100644 index 00000000..fa5b505f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthBaseViewController_Internal.h @@ -0,0 +1,150 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * The methods in this category are exposed so that the FirebaseUI provider frameworks + * can make use of them. They may change in non-breaking releases and should not be + * used publicly. + */ +@interface FUIAuthBaseViewController (Internal) + +/** @fn isValidEmail: + @brief Statically validates email address. + @param email The email address to validate. + */ ++ (BOOL)isValidEmail:(NSString *)email; + +/** @fn showAlertWithMessage: + @brief Displays an alert view with given title and message on top of the current view + controller. + @param message The message of the alert. + */ +- (void)showAlertWithMessage:(NSString *)message; + +/** @fn showAlertWithMessage: + @brief Displays an alert view with given title and message on top of the current view + controller. + @param message The message of the alert. + */ ++ (void)showAlertWithMessage:(NSString *)message; + +/** @fn showAlertWithMessage:presentingViewController: + @brief Displays an alert view with given title and message on top of the current view + controller. + @param message The message of the alert. + @param presentingViewController The controller which shows alert. + */ ++ (void)showAlertWithMessage:(NSString *)message + presentingViewController:(nullable UIViewController *)presentingViewController; + +/** @fn showAlertWithTitle:message: + @brief Displays an alert view with given title, message and action title on top of the + specified view controller. + @param title The title of the alert. + @param message The message of the alert. + @param presentingViewController The controller which shows alert. +*/ ++ (void)showAlertWithTitle:(nullable NSString *)title + message:(nullable NSString *)message + presentingViewController:(nullable UIViewController *)presentingViewController; + +/** @fn showAlertWithTitle:message:actionTitle:actionHandler:dismissTitle:dismissHandler: + @brief Displays an alert view with given title, message and action title on top of the + specified view controller. + @param title The title of the alert. + @param message The message of the alert. + @param actionTitle The title of the action button. + @param actionHandler The block to execute if the action button is tapped. + @param dismissTitle The title of the dismiss button. + @param dismissHandler The block to execute if the cancel button is tapped. + @param presentingViewController The controller which shows alert. +*/ ++ (void)showAlertWithTitle:(nullable NSString *)title + message:(nullable NSString *)message + actionTitle:(nullable NSString *)actionTitle + actionHandler:(nullable FUIAuthAlertActionHandler)actionHandler + dismissTitle:(nullable NSString *)dismissTitle + dismissHandler:(nullable FUIAuthAlertActionHandler)dismissHandler + presentingViewController:(nullable UIViewController *)presentingViewController; + +/** @fn showSignInAlertWithEmail:providerShortName:providerSignInLabel:handler: + @brief Displays an alert to conform with user whether she wants to proceed with the provider. + @param email The email address to sign in with. + @param providerShortName The name of the provider as displayed in the sign-in alert message. + @param providerSignInLabel The name of the provider as displayed in the sign-in alert button. + @param signinHandler Handler for the sign in action of the alert. + @param cancelHandler Handler for the cancel action of the alert. + */ ++ (void)showSignInAlertWithEmail:(NSString *)email + providerShortName:(NSString *)providerShortName + providerSignInLabel:(NSString *)providerSignInLabel + presentingViewController:(UIViewController *)presentingViewController + signinHandler:(FUIAuthAlertActionHandler)signinHandler + cancelHandler:(FUIAuthAlertActionHandler)cancelHandler; + +/** @fn pushViewController: + @brief Push the view controller to the navigation controller of the current view controller + with animation. The pushed view controller will have a fixed "Back" title for back button. + @param viewController The view controller to be pushed. + */ +- (void)pushViewController:(UIViewController *)viewController; + +/** @fn dismissNavigationControllerAnimated:completion: + @brief dismiss navigation controller if it is not the rootViewController. If it is set as + the rootViewController only perform the completion block. + @param animated Use animation when dismissing the ViewControler. + @param completion Code to be executed upon completion + */ +- (void)dismissNavigationControllerAnimated:(BOOL)animated + completion:(void (^)(void))completion; + +/** @fn pushViewController: + @brief Push the view controller to the navigation controller of the current view controller + with animation. The pushed view controller will have a fixed "Back" title for back button. + @param viewController The view controller to be pushed. + @param navigationController The controller where view controller is pushed. + */ ++ (void)pushViewController:(UIViewController *)viewController + navigationController:(UINavigationController *)navigationController; + +/** @fn providerLocalizedName: + @brief Maps provider Id to localized provider name. + */ ++ (NSString *)providerLocalizedName:(NSString *)providerId; + +/** @fn barItemWithTitle:target:action: + @brief Creates multiline @c UIBarButtonItem of fixed width. + @param title The title of the button. + @param target The target object of the @c UIBarButtonItem . + @param action The action called when button is selected. + */ ++ (UIBarButtonItem *)barItemWithTitle:(NSString *)title + target:(nullable id)target + action:(SEL)action; + +/** @fn enableDynamicCellHeightForTableView: + @brief Configures table view in the way than it resizes rows according to their height. + @param tableView The tableView which is going to be configured. + */ +- (void)enableDynamicCellHeightForTableView:(UITableView *)tableView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.h new file mode 100644 index 00000000..0e4aa070 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.h @@ -0,0 +1,62 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthErrors.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAuthErrorUtils + @brief Utility class used to construct @c NSError instances. + */ +@interface FUIAuthErrorUtils : NSObject + +/** @fn errorWithCode: + @brief Creates an error with the specified code. + @param code The error code. + @param userInfo The dictionary containing the error description if available. + @return An @c NSError with the correct code and corresponding description if available. + */ ++ (NSError *)errorWithCode:(FUIAuthErrorCode)code userInfo:(nullable NSDictionary *)userInfo; + +/** @fn userCancelledSignInError + @brief Constructs an @c NSError with the @c FUIAuthErrorCodeUserCancelledSignIn code. + */ ++ (NSError *)userCancelledSignInError; + +/** @fn mergeConflictErrorWithUserInfo:underlyingError: + @brief Constructs an @c NSError with the @c FUIAuthErrorCodeMergeConflict code. + @param userInfo The userInfo dictionary to add to the NSError object. + @param underlyingError The error that was raised by FirebaseAuth while merging accounts. + @return The merge conflict error. + */ ++ (NSError *)mergeConflictErrorWithUserInfo:(NSDictionary *)userInfo + underlyingError:(nullable NSError *)underlyingError; + +/** @fn providerErrorWithUnderlyingError:providerID: + @brief Constructs an @c NSError with the @c FUIAuthErrorCodeProviderError code and a populated + @c NSUnderlyingErrorKey and @c FUIAuthErrorUserInfoProviderIDKey in the + @c NSError.userInfo dictionary. + @param underlyingError The value of the @c NSUnderlyingErrorKey. + @param providerID The value of the @c FUIAuthErrorUserInfoProviderIDKey. + @remarks This error is used when an error from the identity provider cannot be immediately + handled, and should be forwarded to the client. + */ ++ (NSError *)providerErrorWithUnderlyingError:(NSError *)underlyingError + providerID:(NSString *)providerID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.m new file mode 100644 index 00000000..95f27386 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrorUtils.m @@ -0,0 +1,49 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthErrorUtils.h" + +@implementation FUIAuthErrorUtils + ++ (NSError *)errorWithCode:(FUIAuthErrorCode)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:FUIAuthErrorDomain code:code userInfo:userInfo]; +} + ++ (NSError *)userCancelledSignInError { + return [self errorWithCode:FUIAuthErrorCodeUserCancelledSignIn userInfo:nil]; +} + ++ (NSError *)mergeConflictErrorWithUserInfo:(NSDictionary *)userInfo + underlyingError:(NSError *)underlyingError { + NSMutableDictionary *errorInfo = [userInfo mutableCopy]; + if (underlyingError != nil) { + errorInfo[NSUnderlyingErrorKey] = underlyingError; + } + errorInfo[NSLocalizedDescriptionKey] = @"Unable to merge accounts. Check the userInfo dictionary" + @" for the auth credential of the logged-in account."; + return [self errorWithCode:FUIAuthErrorCodeMergeConflict userInfo:[errorInfo copy]]; +} + ++ (NSError *)providerErrorWithUnderlyingError:(NSError *)underlyingError + providerID:(NSString *)providerID { + return [self errorWithCode:FUIAuthErrorCodeProviderError + userInfo:@{ + NSUnderlyingErrorKey : underlyingError, + FUIAuthErrorUserInfoProviderIDKey : providerID + }]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.h new file mode 100644 index 00000000..885d9fa3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.h @@ -0,0 +1,68 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +/** @var FUIAuthErrorDomain + @brief The standard Firebase error domain. + */ +extern NSString *const FUIAuthErrorDomain; + +/** @var FUIAuthErrorUserInfoProviderIDKey + @brief The ID of the identity provider. + */ +extern NSString *const FUIAuthErrorUserInfoProviderIDKey; + +/** @var FUIAuthCredentialKey + @brief The key used to obtain the credential stored within the userInfo dictionary of the + error, if available. + */ +extern NSString *const FUIAuthCredentialKey; + +/** @var FUIAuthErrorCode + @brief Error codes used by FUIAuth. + */ +typedef NS_ENUM(NSUInteger, FUIAuthErrorCode) { + + /** @var FUIAuthErrorCodeUserCancelledSignIn + @brief Indicates the user cancelled a sign-in flow. + */ + FUIAuthErrorCodeUserCancelledSignIn = 1, + + /** @var FUIAuthErrorCodeProviderError + @brief Indicates there's an error from the identity provider. The + @c FUIAuthErrorUserInfoProviderIDKey field in the @c NError.userInfo dictionary will + contain the ID of the identity provider. + */ + FUIAuthErrorCodeProviderError = 2, + + /** @var FUIAuthErrorCodeCantFindProvider + @brief Indicates that @FUIAuth.providers doen't contain current provider (see NSError.userInfo + key @c FUIAuthErrorUserInfoProviderIDKey). + */ + FUIAuthErrorCodeCantFindProvider = 3, + + /** @var FUIAuthErrorCodeMergeConflict + @brief Indicates that a merge conflict occurred while trying to automatically upgrade an + anonymous user. The non-anonymous credential can be obtained from the userInfo dictionary + of the corresponding NSError using the @c FUIAuthCredentialKey. + */ + FUIAuthErrorCodeMergeConflict = 4, +}; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.m new file mode 100644 index 00000000..dc7df99a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthErrors.m @@ -0,0 +1,23 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthErrors.h" + +NSString *const FUIAuthErrorDomain = @"FUIAuthErrorDomain"; + +NSString *const FUIAuthErrorUserInfoProviderIDKey = @"FUIAuthErrorUserInfoProviderIDKey"; + +NSString *const FUIAuthCredentialKey = @"FUIAuthCredentialKey"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.h new file mode 100644 index 00000000..d81a2b2e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FUIAuthBaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAuthPickerViewController + @brief The view controller that displays sign in options to the user. + */ +@interface FUIAuthPickerViewController : FUIAuthBaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.m new file mode 100644 index 00000000..e484d78f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.m @@ -0,0 +1,208 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthPickerViewController.h" + +#import + +#import +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthSignInButton.h" +#import "FUIAuthStrings.h" +#import "FUIAuthUtils.h" +#import "FUIAuth_Internal.h" +#import "FUIPrivacyAndTermsOfServiceView.h" + +/** @var kSignInButtonWidth + @brief The width of the sign in buttons. + */ +static const CGFloat kSignInButtonWidth = 220.0f; + +/** @var kSignInButtonHeight + @brief The height of the sign in buttons. + */ +static const CGFloat kSignInButtonHeight = 40.0f; + +/** @var kSignInButtonVerticalMargin + @brief The vertical margin between sign in buttons. + */ +static const CGFloat kSignInButtonVerticalMargin = 24.0f; + +/** @var kButtonContainerBottomMargin + @brief The magin between sign in buttons and the bottom of the content view. + */ +static const CGFloat kButtonContainerBottomMargin = 48.0f; + +/** @var kButtonContainerTopMargin + @brief The margin between sign in buttons and the top of the content view. + */ +static const CGFloat kButtonContainerTopMargin = 16.0f; + +/** @var kTOSViewBottomMargin + @brief The margin between privacy policy and TOS view and the bottom of the content view. + */ +static const CGFloat kTOSViewBottomMargin = 24.0f; + +/** @var kTOSViewHorizontalMargin + @brief The margin between privacy policy and TOS view and the left or right of the content view. + */ +static const CGFloat kTOSViewHorizontalMargin = 16.0f; + +@implementation FUIAuthPickerViewController { + UIView *_buttonContainerView; + + IBOutlet FUIPrivacyAndTermsOfServiceView *_privacyPolicyAndTOSView; + + IBOutlet UIView *_contentView; + + IBOutlet UIScrollView *_scrollView; +} + +- (instancetype)initWithAuthUI:(FUIAuth *)authUI { + return [self initWithNibName:@"FUIAuthPickerViewController" + bundle:[FUIAuthUtils bundleNamed:FUIAuthBundleName] + authUI:authUI]; +} + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil + bundle:(NSBundle *)nibBundleOrNil + authUI:(FUIAuth *)authUI { + + self = [super initWithNibName:nibNameOrNil + bundle:nibBundleOrNil + authUI:authUI]; + if (self) { + self.title = FUILocalizedString(kStr_AuthPickerTitle); + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Makes sure that embedded scroll view properly handles translucent navigation bar + if (!self.navigationController.navigationBar.isTranslucent) { + self.extendedLayoutIncludesOpaqueBars = true; + } + + if (!self.authUI.shouldHideCancelButton) { + UIBarButtonItem *cancelBarButton = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancelAuthorization)]; + self.navigationItem.leftBarButtonItem = cancelBarButton; + } + if (@available(iOS 13, *)) { + if (!self.authUI.interactiveDismissEnabled) { + self.modalInPresentation = YES; + } + } + + self.navigationItem.backBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:FUILocalizedString(kStr_Back) + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + + NSInteger numberOfButtons = self.authUI.providers.count; + + CGFloat buttonContainerViewHeight = + kSignInButtonHeight * numberOfButtons + kSignInButtonVerticalMargin * (numberOfButtons); + CGRect buttonContainerViewFrame = CGRectMake(0, 0, kSignInButtonWidth, buttonContainerViewHeight); + _buttonContainerView = [[UIView alloc] initWithFrame:buttonContainerViewFrame]; + if (_scrollView) { + [_contentView addSubview:_buttonContainerView]; + } else { + // For backward compatibility. The old auth picker view does not have a scroll view and its + // customized class put the button container view directly into self.view. + [self.view addSubview:_buttonContainerView]; + } + + CGRect buttonFrame = CGRectMake(0, 0, kSignInButtonWidth, kSignInButtonHeight); + for (id providerUI in self.authUI.providers) { + UIButton *providerButton = + [[FUIAuthSignInButton alloc] initWithFrame:buttonFrame providerUI:providerUI]; + [providerButton addTarget:self + action:@selector(didTapSignInButton:) + forControlEvents:UIControlEventTouchUpInside]; + [_buttonContainerView addSubview:providerButton]; + + // Make the frame for the new button. + buttonFrame.origin.y += (kSignInButtonHeight + kSignInButtonVerticalMargin); + } + + _privacyPolicyAndTOSView.authUI = self.authUI; + [_privacyPolicyAndTOSView useFullMessage]; + [_contentView bringSubviewToFront:_privacyPolicyAndTOSView]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + // For backward compatibility. The old auth picker view does not have a scroll view and its + // customized class put the button container view directly into self.view. The following is the + // old layout behavior. + if (!_scrollView) { + CGFloat distanceFromCenterToBottom = + CGRectGetHeight(_buttonContainerView.frame) / 2.0f + kButtonContainerBottomMargin + kTOSViewBottomMargin; + CGFloat centerY = CGRectGetHeight(self.view.bounds) - distanceFromCenterToBottom; + // Compensate for bounds adjustment if any. + centerY += self.view.bounds.origin.y; + _buttonContainerView.center = CGPointMake(self.view.center.x, centerY); + return; + } + + CGFloat buttonContainerHeight = CGRectGetHeight(_buttonContainerView.frame); + CGFloat buttonContainerWidth = CGRectGetWidth(_buttonContainerView.frame); + CGFloat contentViewHeight = kButtonContainerTopMargin + buttonContainerHeight + + kButtonContainerBottomMargin + kTOSViewBottomMargin; + CGFloat contentViewWidth = CGRectGetWidth(self.view.bounds); + _scrollView.frame = self.view.frame; + CGFloat scrollViewHeight; + if (@available(iOS 11.0, *)) { + scrollViewHeight = CGRectGetHeight(_scrollView.frame) - _scrollView.safeAreaInsets.top; + } else { + scrollViewHeight = CGRectGetHeight(_scrollView.frame) + - CGRectGetHeight(self.navigationController.navigationBar.frame) + - CGRectGetHeight([UIApplication sharedApplication].statusBarFrame); + } + CGFloat contentViewY = scrollViewHeight - contentViewHeight; + if (contentViewY < 0) { + contentViewY = 0; + } + _contentView.frame = CGRectMake(0, contentViewY, contentViewWidth, contentViewHeight); + _scrollView.contentSize = CGSizeMake(contentViewWidth, contentViewY + contentViewHeight); + CGFloat buttonContainerLeftMargin = (contentViewWidth - buttonContainerWidth) / 2.0f; + _buttonContainerView.frame =CGRectMake(buttonContainerLeftMargin, + kButtonContainerTopMargin, + buttonContainerWidth, + buttonContainerHeight); + CGFloat privacyViewHeight = CGRectGetHeight(_privacyPolicyAndTOSView.frame); + _privacyPolicyAndTOSView.frame = CGRectMake(kTOSViewHorizontalMargin, contentViewHeight + - privacyViewHeight - kTOSViewBottomMargin, + contentViewWidth - kTOSViewHorizontalMargin*2, + privacyViewHeight); +} + +#pragma mark - Actions + +- (void)didTapSignInButton:(FUIAuthSignInButton *)button { + [self.authUI signInWithProviderUI:button.providerUI + presentingViewController:self + defaultValue:nil]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.xib new file mode 100644 index 00000000..740cc32c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthPickerViewController.xib @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthProvider.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthProvider.h new file mode 100644 index 00000000..dd2a7caf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthProvider.h @@ -0,0 +1,178 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import + +@class FIRAuth; +@class FIRAuthCredential; +@class FIRUserInfo; + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FUIAuthProviderSignInCompletionBlock + @brief The type of block used to notify the auth system of the result of a sign-in flow. + @see FUIAuthProvider.signInWithDefaultValue:presentingViewController:completion: + @param credential The @c FIRAuthCredential object created after user interaction with third + party provider. + @param error The error which may happen during creation of The @c FIRAuthCredential object. + @param result The result of sign-in operation using provided @c FIRAuthCredential object. + @see @c FIRAuth.signInWithCredential:completion: + @param userInfo A dictionary containing additional information about the sign in operation. + @see FUIAuthProviderSignInUserInfoKey + */ +typedef void (^FUIAuthProviderSignInCompletionBlock) ( + FIRAuthCredential *_Nullable credential, + NSError *_Nullable error, + _Nullable FIRAuthResultCallback result, + NSDictionary *_Nullable userInfo); + +/** + @typedef FUIAuthProviderSignInUserInfoKey + @brief A key in a userInfo dictionary corresponding to some supplemental value from + the sign-in operation. + @see FUIAuthProviderSignInCompletionBlock + */ +typedef NSString *FUIAuthProviderSignInUserInfoKey NS_TYPED_ENUM; + +/** + @typedef FUIButtonAlignment + @brief The alignment of the icon and text of the button. +*/ +typedef NS_ENUM(NSInteger, FUIButtonAlignment) { + FUIButtonAlignmentLeading, + FUIButtonAlignmentCenter, +}; + +/** + For Firebase-based authentication operations, use this key to obtain the original auth result + that was returned from the sign-in operation. + */ +static FUIAuthProviderSignInUserInfoKey FUIAuthProviderSignInUserInfoKeyAuthDataResult = + @"FUIAuthProviderSignInUserInfoKeyAuthDataResult"; + +/** @protocol FUIAuthProvider + @brief Represents an authentication provider (such as Google Sign In or Facebook Login) which + can be used with the AuthUI classes (like @c FUIAuthPickerViewController). + @remarks @c FUIAuth.signInProviders is populated with a list of @c FUIAuthProvider instances + to provide users with sign-in options. + */ +@protocol FUIAuthProvider + +/** @property providerID + @brief A unique identifier for the provider. + */ +@property(nonatomic, copy, readonly, nullable) NSString *providerID; + +/** @property shortName + @brief A short display name for the provider. + */ +@property(nonatomic, copy, readonly) NSString *shortName; + +/** @property signInLabel + @brief A localized label for the provider's sign-in button. + */ +@property(nonatomic, copy, readonly) NSString *signInLabel; + +/** @property icon + @brief The icon image of the provider. + */ +@property(nonatomic, strong, readonly) UIImage *icon; + +/** @property buttonBackgroundColor + @brief The background color that should be used for the sign in button of the provider. + */ +@property(nonatomic, strong, readonly) UIColor *buttonBackgroundColor; + +/** @property buttonTextColor + @brief The text color that should be used for the sign in button of the provider. + */ +@property(nonatomic, strong, readonly) UIColor *buttonTextColor; + +/** @property buttonAlignment + @brief The alignment of the icon and text of the button. + */ +@property(nonatomic, readwrite) FUIButtonAlignment buttonAlignment; + +/** @fn signInWithEmail:presentingViewController:completion: + @brief Called when the user wants to sign in using this auth provider. + @remarks Implementors should invoke the completion block when the sign-in process has terminated + or is canceled. There are two valid combinations of parameters; either @c credentials and + @c userInfo are both non-nil, or @c error is non-nil. Errors must specify an error code + which is one of the @c FIRAuthErrorCode codes. It is very important that all possible code + paths eventually call this method to inform the auth system of the result of the sign-in + flow. + @param email The email address of the user if it's known. + @param presentingViewController The view controller used to present the UI. + @param completion See remarks. A block which should be invoked when the sign-in process + (using @c FIRAuthCredential) completes. + */ +- (void)signInWithEmail:(nullable NSString *)email + presentingViewController:(nullable UIViewController *)presentingViewController + completion:(nullable FUIAuthProviderSignInCompletionBlock)completion +__attribute__((deprecated("This is deprecated API and will be removed in a future release." + "Use signInWithDefaultValue:presentingViewController:completion:"))); + +/** @fn signInWithDefaultValue:presentingViewController:completion: + @brief Called when the user wants to sign in using this auth provider. + @remarks Implementors should invoke the completion block when the sign-in process has terminated + or is canceled. There are two valid combinations of parameters; either @c credentials and + @c userInfo are both non-nil, or @c error is non-nil. Errors must specify an error code + which is one of the @c FIRAuthErrorCode codes. It is very important that all possible code + paths eventually call this method to inform the auth system of the result of the sign-in + flow. + @param defaultValue The default initialization value of the provider (email, phone number etc.). + @param presentingViewController The view controller used to present the UI. + @param completion See remarks. A block which should be invoked when the sign-in process + (using @c FIRAuthCredential) completes. + */ +- (void)signInWithDefaultValue:(nullable NSString *)defaultValue + presentingViewController:(nullable UIViewController *)presentingViewController + completion:(nullable FUIAuthProviderSignInCompletionBlock)completion; + +/** @fn signOut + @brief Called when the user wants to sign out. + */ +- (void)signOut; + +/** @property accessToken + @brief User Access Token obtained during sign in. + */ +@property(nonatomic, copy, readonly, nullable) NSString *accessToken; + +@optional; + +/** @property idToken + @brief User Id Token obtained during sign in. Not all providers can return, thus it's optional. + */ +@property(nonatomic, copy, readonly, nullable) NSString *idToken; + +/** @fn email + @brief The email address associated with this provider, if any. + */ +- (NSString *)email; + +/** @fn handleOpenURL: + @brief May be used to help complete a sign-in flow which requires a callback from Safari. + @param URL The URL which may be handled by the auth provider if an URL is expected. + @param sourceApplication The application which tried opening the URL. + @return YES if your auth provider handled the URL. NO otherwise. + */ +- (BOOL)handleOpenURL:(NSURL *)URL sourceApplication:(nullable NSString *)sourceApplication; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.h new file mode 100644 index 00000000..3456a391 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.h @@ -0,0 +1,68 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FUIAuthProvider.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAuthSignInButton + @brief Button representing an identity provider on the auth picker screen that starts + authentication with the provider when touched. + */ +@interface FUIAuthSignInButton : UIButton + +/** @property provider + @brief The provider UI instance associated with this button. Can be nil. + */ +@property(nonatomic, strong, readonly, nullable) id providerUI; + +/** @fn initWithFrame: + @brief Please use initWithFrame:image:text:backgroundColor:textColor:. + */ +- (id)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +/** @fn initWithCoder: + @brief Please use initWithFrame:image:text:backgroundColor:textColor:. + */ +- (id)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; + +/** @fn initWithFrame:image:text:backgroundColor:textColor: + @brief Designated initializer. + @param frame The initial frame for the button. + @param image Logo image for the button. + @param text Button text. + @param backgroundColor Background color of the button in the normal state. + @param textColor Color of the button text. + */ +- (id)initWithFrame:(CGRect)frame + image:(UIImage *)image + text:(NSString *)text + backgroundColor:(UIColor *)backgroundColor + textColor:(UIColor *)textColor + buttonAlignment:(FUIButtonAlignment)buttonAlignment NS_DESIGNATED_INITIALIZER; + +/** @fn initWithFrame:providerUI: + @brief Convenience initalizer. + @param frame The initial frame for the button. + @param providerUI The provider UI instance associated with this button. + */ +- (id)initWithFrame:(CGRect)frame providerUI:(id)providerUI; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.m new file mode 100644 index 00000000..ef7c2965 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthSignInButton.m @@ -0,0 +1,116 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthSignInButton.h" + +#import "FUIAuthProvider.h" +#import "FUIAuthUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kCornerRadius + @brief Corner radius of the button. + */ +static const int kCornerRadius = 2.0f; + +/** @var kDropShadowAlpha + @brief Opacity of the drop shadow of the button. + */ +static const CGFloat kDropShadowAlpha = 0.24f; + +/** @var kDropShadowRadius + @brief Radius of the drop shadow of the button. + */ +static const CGFloat kDropShadowRadius = 2.0f; + +/** @var kDropShadowYOffset + @brief Vertical offset of the drop shadow of the button. + */ +static const CGFloat kDropShadowYOffset = 2.0f; + +/** @var kFontSize + @brief Button text font size. + */ +static const CGFloat kFontSize = 12.0f; + +@implementation FUIAuthSignInButton + +- (instancetype)initWithFrame:(CGRect)frame + image:(UIImage *)image + text:(NSString *)text + backgroundColor:(UIColor *)backgroundColor + textColor:(UIColor *)textColor + buttonAlignment:(FUIButtonAlignment)buttonAlignment { + self = [super initWithFrame:frame]; + if (!self) { + return nil; + } + + self.backgroundColor = backgroundColor; + [self setTitle:text forState:UIControlStateNormal]; + [self setTitleColor:textColor forState:UIControlStateNormal]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:kFontSize]; + self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + [self setImage:image forState:UIControlStateNormal]; + + CGFloat paddingTitle = 8.0f; + CGFloat contentWidth = self.imageView.frame.size.width + paddingTitle + self.titleLabel.frame.size.width; + CGFloat paddingImage = 8.0f; + if (buttonAlignment == FUIButtonAlignmentCenter) { + paddingImage = (frame.size.width - contentWidth) / 2 - 4.0f; + } + BOOL isLTRLayout = [[UIApplication sharedApplication] userInterfaceLayoutDirection] == + UIUserInterfaceLayoutDirectionLeftToRight; + if (isLTRLayout) { + [self setTitleEdgeInsets:UIEdgeInsetsMake(0, paddingTitle, 0, paddingImage + paddingTitle)]; + [self setContentEdgeInsets:UIEdgeInsetsMake(0, paddingImage, 0, -paddingImage - paddingTitle)]; + [self setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft]; + } else { + [self setTitleEdgeInsets:UIEdgeInsetsMake(0, paddingImage + paddingTitle, 0, paddingTitle)]; + [self setContentEdgeInsets:UIEdgeInsetsMake(0, -paddingImage - paddingTitle, 0, paddingImage)]; + [self setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight]; + } + + + + self.layer.cornerRadius = kCornerRadius; + + // Add a drop shadow. + self.layer.masksToBounds = NO; + self.layer.shadowColor = [UIColor blackColor].CGColor; + self.layer.shadowOpacity = kDropShadowAlpha; + self.layer.shadowRadius = kDropShadowRadius; + self.layer.shadowOffset = CGSizeMake(0, kDropShadowYOffset); + + self.adjustsImageWhenHighlighted = NO; + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame providerUI:(id)providerUI { + _providerUI = providerUI; + return [self initWithFrame:frame + image:providerUI.icon + text:providerUI.signInLabel + backgroundColor:providerUI.buttonBackgroundColor + textColor:providerUI.buttonTextColor + buttonAlignment:providerUI.buttonAlignment]; +} + +@end + +NS_ASSUME_NONNULL_END + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.h new file mode 100644 index 00000000..3ddd4790 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.h @@ -0,0 +1,147 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const kStr_ASCellAddPassword; +extern NSString *const kStr_ASCellChangePassword; +extern NSString *const kStr_ASCellDeleteAccount; +extern NSString *const kStr_ASCellEmail; +extern NSString *const kStr_ASCellName; +extern NSString *const kStr_ASCellSignOut; +extern NSString *const kStr_ASSectionTitleLinkedAccounts; +extern NSString *const kStr_ASSectionTitleProfile; +extern NSString *const kStr_ASSectionTitleSecurity; +extern NSString *const kStr_AccountDisabledError; +extern NSString *const kStr_AuthPickerTitle; +extern NSString *const kStr_Back; +extern NSString *const kStr_Cancel; +extern NSString *const kStr_CannotAuthenticateError; +extern NSString *const kStr_ChoosePassword; +extern NSString *const kStr_Close; +extern NSString *const kStr_ConfirmEmail; +extern NSString *const kStr_Email; +extern NSString *const kStr_EmailAlreadyInUseError; +extern NSString *const kStr_EmailSentConfirmationMessage; +extern NSString *const kStr_EnterYourEmail; +extern NSString *const kStr_EnterYourPassword; +extern NSString *const kStr_Error; +extern NSString *const kStr_ExistingAccountTitle; +extern NSString *const kStr_FirstAndLastName; +extern NSString *const kStr_ForgotPassword; +extern NSString *const kStr_InvalidEmailError; +extern NSString *const kStr_InvalidPasswordError; +extern NSString *const kStr_Name; +extern NSString *const kStr_Next; +extern NSString *const kStr_OK; +extern NSString *const kStr_Password; +extern NSString *const kStr_PasswordRecoveryEmailSentMessage; +extern NSString *const kStr_PasswordRecoveryEmailSentTitle; +extern NSString *const kStr_PasswordRecoveryMessage; +extern NSString *const kStr_PasswordRecoveryTitle; +extern NSString *const kStr_PasswordVerificationMessage; +extern NSString *const kStr_ProviderUsedPreviouslyMessage; +extern NSString *const kStr_Save; +extern NSString *const kStr_Send; +extern NSString *const kStr_Resend; +extern NSString *const kStr_SignedIn; +extern NSString *const kStr_SignInTitle; +extern NSString *const kStr_SignInTooManyTimesError; +extern NSString *const kStr_SignInWithEmail; +extern NSString *const kStr_SignInEmailSent; +extern NSString *const kStr_SignUpTitle; +extern NSString *const kStr_SignUpTooManyTimesError; +extern NSString *const kStr_TermsOfService; +extern NSString *const kStr_TroubleGettingEmailTitle; +extern NSString *const kStr_TroubleGettingEmailMessage; +extern NSString *const kStr_PrivacyPolicy; +extern NSString *const kStr_TermsOfServiceMessage; +extern NSString *const kStr_UserNotFoundError; +extern NSString *const kStr_WeakPasswordError; +extern NSString *const kStr_WrongPasswordError; +extern NSString *const kStr_CantFindProvider; +extern NSString *const kStr_EmailsDontMatch; +extern NSString *const kStr_ForgotPassword; +extern NSString *const kStr_VerifyItsYou; +extern NSString *const kStr_DeleteAccountConfirmationTitle; +extern NSString *const kStr_DeleteAccountBody; +extern NSString *const kStr_DeleteAccountConfirmationMessage; +extern NSString *const kStr_Delete; +extern NSString *const kStr_DeleteAccountControllerTitle; +extern NSString *const kStr_ActionCantBeUndone; +extern NSString *const kStr_UnlinkTitle; +extern NSString *const kStr_UnlinkAction; +extern NSString *const kStr_UnlinkConfirmationTitle; +extern NSString *const kStr_UnlinkConfirmationMessage; +extern NSString *const kStr_UnlinkConfirmationActionTitle; +extern NSString *const kStr_UpdateEmailAlertMessage; +extern NSString *const kStr_UpdateEmailVerificationAlertMessage; +extern NSString *const kStr_AddPasswordAlertMessage; +extern NSString *const kStr_EditPasswordAlertMessage; +extern NSString *const kStr_ReauthenticateEditPasswordAlertMessage; +extern NSString *const kStr_AddPasswordTitle; +extern NSString *const kStr_EditPasswordTitle; +extern NSString *const kStr_EditNameTitle; +extern NSString *const kStr_EditEmailTitle; +extern NSString *const kStr_ProviderTitlePassword; +extern NSString *const kStr_ProviderTitleGoogle; +extern NSString *const kStr_ProviderTitleFacebook; +extern NSString *const kStr_ProviderTitleTwitter; +extern NSString *const kStr_SignInWithProvider; +extern NSString *const kStr_PlaceholderEnterName; +extern NSString *const kStr_PlaceholderEnterEmail; +extern NSString *const kStr_PlaceholderEnterPassword; +extern NSString *const kStr_PlaceholderChosePassword; +extern NSString *const kStr_PlaceholderNewPassword; +extern NSString *const kStr_ForgotPasswordTitle; + +#ifdef __cplusplus +extern "C" { +#endif + +/** @fn FUILocalizedString + @brief Gets a localized string from a name. + @param key The key value of the string. + @return The string by the key localized in the current locale located in default table. + */ +NSString *FUILocalizedString(NSString *key); + +/** @fn FUILocalizedStringFromTable + @brief Gets a localized string from a name. + @param key The key value of the string. + @param table The localization table name. + @return The string by the key localized in the current locale. +*/ +NSString *FUILocalizedStringFromTable(NSString *key, NSString *table); + +/** @fn FUILocalizedStringFromTableInBundle + @brief Gets a localized string from a name. + @param key The key value of the string. + @param table The localization table name. + @param bundleName The value of bundlu to look for. If nil is passed looking in apps bundle. + @return The string by the key localized in the current locale. +*/ +NSString *FUILocalizedStringFromTableInBundle(NSString *key, + NSString *table, + NSString *_Nullable bundleName); + +#ifdef __cplusplus +} +#endif + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.m new file mode 100644 index 00000000..88d550b2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthStrings.m @@ -0,0 +1,160 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FUIAuthStrings.h" + +#import "FUIAuth.h" +#import "FUIAuthUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +// AuthUI string keys. +NSString *const kStr_ASCellAddPassword = @"AS_AddPassword"; +NSString *const kStr_ASCellChangePassword = @"AS_ChangePassword"; +NSString *const kStr_ASCellDeleteAccount = @"AS_DeleteAccount"; +NSString *const kStr_ASCellEmail = @"AS_Email"; +NSString *const kStr_ASCellName = @"AS_Name"; +NSString *const kStr_ASCellSignOut = @"AS_SignOut"; +NSString *const kStr_ASSectionTitleLinkedAccounts = @"AS_SectionLinkedAccounts"; +NSString *const kStr_ASSectionTitleProfile = @"AS_SectionProfile"; +NSString *const kStr_ASSectionTitleSecurity = @"AS_SectionSecurity"; +NSString *const kStr_AccountDisabledError = @"AccountDisabledError"; +NSString *const kStr_AuthPickerTitle = @"AuthPickerTitle"; +NSString *const kStr_Back = @"Back"; +NSString *const kStr_Cancel = @"Cancel"; +NSString *const kStr_CannotAuthenticateError = @"CannotAuthenticateError"; +NSString *const kStr_ChoosePassword = @"ChoosePassword"; +NSString *const kStr_Close = @"Close"; +NSString *const kStr_ConfirmEmail = @"ConfirmEmail"; +NSString *const kStr_Email = @"Email"; +NSString *const kStr_EmailAlreadyInUseError = @"EmailAlreadyInUseError"; +NSString *const kStr_EmailSentConfirmationMessage = @"EmailSentConfirmationMessage"; +NSString *const kStr_EnterYourEmail = @"EnterYourEmail"; +NSString *const kStr_EnterYourPassword = @"EnterYourPassword"; +NSString *const kStr_Error = @"Error"; +NSString *const kStr_ExistingAccountTitle = @"ExistingAccountTitle"; +NSString *const kStr_FirstAndLastName = @"FirstAndLastName"; +NSString *const kStr_ForgotPassword = @"ForgotPassword"; +NSString *const kStr_InvalidEmailError = @"InvalidEmailError"; +NSString *const kStr_InvalidPasswordError = @"InvalidPasswordError"; +NSString *const kStr_Name = @"Name"; +NSString *const kStr_Next = @"Next"; +NSString *const kStr_OK = @"OK"; +NSString *const kStr_Password = @"Password"; +NSString *const kStr_PasswordRecoveryEmailSentMessage = @"PasswordRecoveryEmailSentMessage"; +NSString *const kStr_PasswordRecoveryEmailSentTitle = @"PasswordRecoveryEmailSentTitle"; +NSString *const kStr_PasswordRecoveryMessage = @"PasswordRecoveryMessage"; +NSString *const kStr_PasswordRecoveryTitle = @"PasswordRecoveryTitle"; +NSString *const kStr_PasswordVerificationMessage = @"PasswordVerificationMessage"; +NSString *const kStr_ProviderUsedPreviouslyMessage = @"ProviderUsedPreviouslyMessage"; +NSString *const kStr_Save = @"Save"; +NSString *const kStr_Send = @"Send"; +NSString *const kStr_Resend = @"Resend"; +NSString *const kStr_SignedIn = @"SignedIn"; +NSString *const kStr_SignInTitle = @"SignInTitle"; +NSString *const kStr_SignInTooManyTimesError = @"SignInTooManyTimesError"; +NSString *const kStr_SignInWithEmail = @"SignInWithEmail"; +NSString *const kStr_SignInEmailSent = @"SignInEmailSent"; +NSString *const kStr_SignUpTitle = @"SignUpTitle"; +NSString *const kStr_SignUpTooManyTimesError = @"SignUpTooManyTimesError"; +NSString *const kStr_TermsOfService = @"TermsOfService"; +NSString *const kStr_TroubleGettingEmailTitle = @"TroubleGettingEmailTitle"; +NSString *const kStr_TroubleGettingEmailMessage = @"TroubleGettingEmailMessage"; +NSString *const kStr_PrivacyPolicy = @"PrivacyPolicy"; +NSString *const kStr_TermsOfServiceMessage = @"TermsOfServiceMessage"; +NSString *const kStr_UserNotFoundError = @"UserNotFoundError"; +NSString *const kStr_WeakPasswordError = @"WeakPasswordError"; +NSString *const kStr_WrongPasswordError = @"WrongPasswordError"; +NSString *const kStr_CantFindProvider = @"CantFindProvider"; +NSString *const kStr_EmailsDontMatch = @"EmailsDontMatch"; +NSString *const kStr_VerifyItsYou = @"VerifyItsYou"; +NSString *const kStr_DeleteAccountConfirmationTitle = @"DeleteAccountConfirmationTitle"; +NSString *const kStr_DeleteAccountBody = @"DeleteAccountBody"; +NSString *const kStr_DeleteAccountConfirmationMessage = @"DeleteAccountConfirmationMessage"; +NSString *const kStr_Delete = @"Delete"; +NSString *const kStr_DeleteAccountControllerTitle = @"DeleteAccountControllerTitle"; +NSString *const kStr_ActionCantBeUndone = @"ActionCantBeUndone"; +NSString *const kStr_UnlinkTitle = @"UnlinkTitle"; +NSString *const kStr_UnlinkAction = @"UnlinkAction"; +NSString *const kStr_UnlinkConfirmationTitle = @"UnlinkConfirmationTitle"; +NSString *const kStr_UnlinkConfirmationMessage = @"UnlinkConfirmationMessage"; +NSString *const kStr_UnlinkConfirmationActionTitle = @"UnlinkConfirmationActionTitle"; +NSString *const kStr_UpdateEmailAlertMessage = @"UpdateEmailAlertMessage"; +NSString *const kStr_UpdateEmailVerificationAlertMessage = @"UpdateEmailVerificationAlertMessage"; +NSString *const kStr_EditEmailTitle = @"EditEmailTitle"; +NSString *const kStr_EditNameTitle = @"EditNameTitle"; +NSString *const kStr_AddPasswordAlertMessage = @"AddPasswordAlertMessage"; +NSString *const kStr_EditPasswordAlertMessage = @"EditPasswordAlertMessage"; +NSString *const kStr_ReauthenticateEditPasswordAlertMessage = @"ReauthenticateEditPasswordAlertMessage"; +NSString *const kStr_AddPasswordTitle = @"AddPasswordTitle"; +NSString *const kStr_EditPasswordTitle = @"EditPasswordTitle"; +NSString *const kStr_ProviderTitlePassword = @"ProviderTitlePassword"; +NSString *const kStr_ProviderTitleGoogle = @"ProviderTitleGoogle"; +NSString *const kStr_ProviderTitleFacebook = @"ProviderTitleFacebook"; +NSString *const kStr_ProviderTitleTwitter = @"ProviderTitleTwitter"; +NSString *const kStr_SignInWithProvider = @"SignInWithProvider"; +NSString *const kStr_PlaceholderEnterName = @"PlaceholderEnterName"; +NSString *const kStr_PlaceholderEnterEmail = @"PlaceholderEnterEmail"; +NSString *const kStr_PlaceholderEnterPassword = @"PlaceholderEnterPassword"; +NSString *const kStr_PlaceholderChosePassword = @"PlaceholderChosePassword"; +NSString *const kStr_PlaceholderNewPassword = @"PlaceholderNewPassword"; +NSString *const kStr_ForgotPasswordTitle = @"ForgotPasswordTitle"; + +/** @var kKeyNotFound + @brief The value returned if the key is not found in the table. + */ +NSString *const kKeyNotFound = @"KeyNotFound"; + +/** @var kTableName + @brief The name of the strings table to search for localized strings. + */ +NSString *const kTableName = @"FirebaseAuthUI"; + +NSString *FUILocalizedString(NSString *key) { + return FUILocalizedStringFromTable(key, kTableName); +} + +NSString *FUILocalizedStringFromTable(NSString *key, NSString *table) { + return FUILocalizedStringFromTableInBundle(key, table, kTableName); +} + +NSString *FUILocalizedStringFromTableInBundle(NSString *key, + NSString *table, + NSString *_Nullable bundleName) { + // Don't load defaultAuthUI if the default app isn't configured. We don't recommend + // people do this in our docs, but if for whatever reason they want to use a custom + // app, this code shouldn't crash. + if ([FIRApp defaultApp] != nil) { + NSBundle *customStringsBundle = [FUIAuth defaultAuthUI].customStringsBundle; + if (customStringsBundle) { + NSString *localizedString = [customStringsBundle localizedStringForKey:key + value:kKeyNotFound + table:table]; + if (![kKeyNotFound isEqual:localizedString]) { + return localizedString; + } + } + } + NSBundle *frameworkBundle = [FUIAuthUtils bundleNamed:bundleName]; + if (frameworkBundle == nil) { + frameworkBundle = [NSBundle mainBundle]; + } + return [frameworkBundle localizedStringForKey:key value:nil table:table]; +} + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.h new file mode 100644 index 00000000..ed6ffd43 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +/** @class FUIAuthTableHeaderView + @brief A table header view that contains a title label and a detail label. + */ +@interface FUIAuthTableHeaderView : UIView + +/** @property titleLabel + @brief The title label in this table header view. + */ +@property(nonatomic, strong) UILabel *titleLabel; + +/** @property detailLabel + @brief The detail label in this table header view. + */ +@property(nonatomic, strong) UILabel *detailLabel; + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.m new file mode 100644 index 00000000..19b29f9f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableHeaderView.m @@ -0,0 +1,83 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthTableHeaderView.h" + +/** @var kLabelHorizontalMargin + @brief The horizontal margin around any @c UILabel. + */ +static const CGFloat kLabelHorizontalMargin = 8.0f; + +/** @var kLabelVerticalMargin + @brief The veritcal margin around any @c UILabel. + */ +static const CGFloat kLabelVerticalMargin = 16.0f; + +@implementation FUIAuthTableHeaderView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont boldSystemFontOfSize:16.0f]; + [self addSubview:_titleLabel]; + + _detailLabel = [[UILabel alloc] init]; + _detailLabel.font = [UIFont systemFontOfSize:14.0f]; + _detailLabel.numberOfLines = 0; + [self addSubview:_detailLabel]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + [_titleLabel sizeToFit]; + + CGRect contentRect = CGRectInset(self.bounds, kLabelHorizontalMargin, kLabelVerticalMargin); + CGRect titleLabelFrame, detailLabelFrame, space; + CGRectDivide(contentRect, &titleLabelFrame, &contentRect, + CGRectGetHeight(_titleLabel.frame), CGRectMinYEdge); + CGRectDivide(contentRect, &space, &detailLabelFrame, kLabelVerticalMargin, CGRectMinYEdge); + + _titleLabel.frame = titleLabelFrame; + _detailLabel.frame = detailLabelFrame; +} + +- (CGSize)sizeThatFits:(CGSize)size { + CGFloat labelWidth = size.width - kLabelHorizontalMargin * 2; + CGFloat titleLabelHeight = [[self class] sizeForLabel:_titleLabel maxWidth:labelWidth].height; + CGFloat detailLabelHeight = [[self class] sizeForLabel:_detailLabel maxWidth:labelWidth].height; + CGFloat height = titleLabelHeight + detailLabelHeight + kLabelVerticalMargin * 3; + return CGSizeMake(size.width, height); +} + +#pragma mark - Utility + +/** @fn sizeForLabel:maxWidth: + @brief Calculate the with of the @c UILabel with the given maximum width. + @return The calculated size. + */ ++ (CGSize)sizeForLabel:(UILabel *)label maxWidth:(CGFloat)maxWidth { + CGRect rect = [label.text boundingRectWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{ NSFontAttributeName : label.font } + context:nil]; + return CGRectIntegral(rect).size; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.h new file mode 100644 index 00000000..e8357c5d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIAuthTableViewCell + @brief A common table view cell that can be used in multiple view controllers. + */ +@interface FUIAuthTableViewCell : UITableViewCell + +/** @property label + @brief The label that describes the purpose of @c textField. + */ +@property(nonatomic, strong) IBOutlet UILabel *label; + +/** @property textField + @brief The text field that collects user's input. + */ +@property(nonatomic, strong) IBOutlet UITextField *textField; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.m new file mode 100644 index 00000000..443e9c75 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.m @@ -0,0 +1,35 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthTableViewCell.h" + +@implementation FUIAuthTableViewCell + +- (void)awakeFromNib { + [super awakeFromNib]; + + if (@available(iOS 13.0, *)) { + self.textField.textColor = [UIColor labelColor]; + self.label.textColor = [UIColor labelColor]; + } +} + +- (void)setLabel:(UILabel *)label { + _label = label; + [self layoutIfNeeded]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.xib new file mode 100644 index 00000000..4060491f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthTableViewCell.xib @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.h new file mode 100644 index 00000000..10bc8b06 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/* Name of the FirebaseAuthUI resource bundle. */ +extern NSString *const FUIAuthBundleName; + +/** @class FUIAuthUtils + @brief Provides utility methods for Firebase Auth UI. + */ +@interface FUIAuthUtils : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** @fn bundleNamed: + @brief Gets the framework bundle for specified name + @param bundleName Name of the bundle to retreive. If nil, this returns the default bundle for + FirebaseUI. + */ ++ (nullable NSBundle *)bundleNamed:(nullable NSString *)bundleName; + +/** @fn imageNamed:fromBundle: + @brief Gets a UIImage with the given name, assuming it's a png. + @param name Name of the image to retreive. + @param bundleNameOrNil Name of the bundle to retreive. If nil, this method will look into the + default FirebaseUI framework bundle. + */ ++ (nullable UIImage *)imageNamed:(NSString *)name fromBundleNameOrNil:(nullable NSString *)bundleNameOrNil; + +/** @fn imageNamed:fromBundle: + @brief Gets a UIImage with the given name, assuming it's a png. + @param name Name of the image to retreive. + @param bundle The bundle to retrieve the image from. If nil, this method will look into the + default FirebaseUI framework bundle. + */ ++ (nullable UIImage *)imageNamed:(NSString *)name fromBundle:(nullable NSBundle *)bundle; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.m new file mode 100644 index 00000000..e6eb7d91 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuthUtils.m @@ -0,0 +1,59 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthUtils.h" + +NSString *const FUIAuthBundleName = @"FirebaseAuthUI"; + +@implementation FUIAuthUtils + ++ (nullable NSBundle *)bundleNamed:(nullable NSString *)bundleName { + NSBundle *frameworkBundle = nil; + if (!bundleName) { + bundleName = FUIAuthBundleName; + } + NSString *path = [[NSBundle mainBundle] pathForResource:bundleName ofType:@"bundle"]; + if (!path) { + // Check framework resources if bundle isn't present in main bundle. + path = [[NSBundle mainBundle] pathForResource:bundleName ofType:@"framework"]; + } + frameworkBundle = [NSBundle bundleWithPath:path]; + if (!frameworkBundle) { + frameworkBundle = [NSBundle bundleForClass:[self class]]; + } + return frameworkBundle; +} + ++ (nullable UIImage *)imageNamed:(NSString *)name fromBundle:(nullable NSBundle *)bundle { + if (!bundle) { + bundle = [self bundleNamed:nil]; + } + NSString *path = [bundle pathForResource:name ofType:@"png"]; + if (!path) { + NSLog(@"Warning: Unable to find asset %@ in bundle %@.", name, bundle); + } + return [UIImage imageWithContentsOfFile:path]; +} + ++ (nullable UIImage *)imageNamed:(NSString *)name fromBundleNameOrNil:(nullable NSString *)bundleNameOrNil { + NSString *path = [[FUIAuthUtils bundleNamed:bundleNameOrNil] pathForResource:name ofType:@"png"]; + if (!path) { + NSLog(@"Warning: Unable to find asset %@ in bundle named %@.", name, bundleNameOrNil); + } + return [UIImage imageWithContentsOfFile:path]; +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth_Internal.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth_Internal.h new file mode 100644 index 00000000..9da1d27e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIAuth_Internal.h @@ -0,0 +1,100 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuth.h" + +@class FUIAuthBaseViewController; + +/** @typedef FUIEmailHintSignInCallback + @brief The type of block invoked when an emailHint sign-in event completes. + + @param authResult Optionally; Result of sign-in request containing both the user and + the additional user info associated with the user. + @param error Optionally; the error which occurred - or nil if the request was successful. + @param credential Optionally; The credential used to sign-in. + */ +typedef void (^FUIEmailHintSignInCallback)(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error, + FIRAuthCredential *_Nullable credential); + +NS_ASSUME_NONNULL_BEGIN + + +/** + * The methods defined in this file are for use in the FirebaseUI provider libraries. + * They may break in non-major releases and are not for public use. + */ +@protocol FUIEmailAuthProvider + +- (void)handleAccountLinkingForEmail:(NSString *)email + newCredential:(FIRAuthCredential *)newCredential + presentingViewController:(UIViewController *)presentingViewController + signInResult:(_Nullable FIRAuthResultCallback)result; + +- (void)signInWithEmailHint:(NSString *)emailHint + presentingViewController:(FUIAuthBaseViewController *)presentingViewController + originalError:(NSError *)originalError + completion:(FUIEmailHintSignInCallback)completion; + +@end + +@interface FUIAuth () + +/** @fn invokeResultCallbackWithAuthDataResult:error: + @brief Invokes the auth UI result callback. + @param authDataResult The sign in data result, if any. + @param url The url, if any. + @param error The error which occurred, if any. + */ +- (void)invokeResultCallbackWithAuthDataResult:(nullable FIRAuthDataResult *)authDataResult + URL:(nullable NSURL *)url + error:(nullable NSError *)error; + +/** @fn invokeOperationCallback:error: + @brief Invokes the auth UI operation callback. + @param operation The executed operation. + @param error The error which occurred, if any. + */ +- (void)invokeOperationCallback:(FUIAccountSettingsOperationType)operation + error:(NSError *_Nullable)error; + + +/** @fn providerWithID: + @brief Returns first provider (if it exists) with specified provider ID. + @param providerID The ID of the provider. + */ +- (nullable id)providerWithID:(NSString *)providerID; + +/** @fn signInWithProviderUI:presentingViewController:defaultValue: + @brief Signs in with specified provider. + @see FUIAuthDelegate.authUI:didSignInWithAuthDataResult:URL:error: for method callback. + @param providerUI The authentication provider used for signing in. + @param presentingViewController The view controller used to present the UI. + @param defaultValue The provider default initialization value (e.g. email or phone number) + used for signing in. + */ +- (void)signInWithProviderUI:(id)providerUI + presentingViewController:(UIViewController *)presentingViewController + defaultValue:(nullable NSString *)defaultValue; + +/** @property emailAuthProvider + @brief The email auth provider, if any, that will be displayed in the default sign-in UI. + */ +@property(nonatomic, weak, nullable) id emailAuthProvider; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.h new file mode 100644 index 00000000..ca75c72b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@class FUIAuth; + +NS_ASSUME_NONNULL_BEGIN + +@interface FUIPrivacyAndTermsOfServiceView : UITextView + +/** @fn useFullMessage + @brief Display Privacy and Terms of Service message in full form. + */ +- (void)useFullMessage; + +/** @fn useFooterMessage + @brief Display Privacy and Terms of Service link, which usually are placed as footer. + */ +- (void)useFooterMessage; + +/** @property authUI + @brief the @c FUIAuth instance whose bundle will be used to populate the view's terms of service and + privacy policy content. If this property is nil, the default @c FUIAuth instance's terms of service and + privacy policy will be used. + */ +@property(nonatomic, strong, nullable) FUIAuth *authUI; + +@end + +@interface FUIPrivacyAndTermsOfServiceView (Protected) + +/** @fn privacyPolicyAndTOSMessageFromFormat: + @brief produce the Privacy and Terms of Service attributed string based on a customized format. + @param format the customized format with two placeholder for Privacy and Terms of Service + respectively. + @return the Privacy and Terms of Service attributed string. + */ +- (NSAttributedString *)privacyPolicyAndTOSMessageFromFormat:(NSString *)format; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.m new file mode 100644 index 00000000..c07d3d6e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.m @@ -0,0 +1,98 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIPrivacyAndTermsOfServiceView.h" + +#import +#import "FUIAuth.h" +#import "FUIAuthStrings.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation FUIPrivacyAndTermsOfServiceView + +#pragma mark - Public + +- (void)useFullMessage { + NSAttributedString *fullMessage = [self fullPrivacyPolicyAndTOSMessage]; + self.attributedText = fullMessage; + self.textAlignment = NSTextAlignmentLeft; +} + +- (void)useFooterMessage { + NSAttributedString *footerMessage = [self footerPrivacyPolicyAndTOSMessage]; + self.attributedText = footerMessage; + self.textAlignment = NSTextAlignmentRight; +} + +#pragma mark - Protected + +- (NSAttributedString *)privacyPolicyAndTOSMessageFromFormat:(NSString *)format { + FUIAuth *authUI = self.authUI ?: [FUIAuth defaultAuthUI]; + NSURL *TOSURL = authUI.TOSURL; + NSURL *privacyPolicyURL = authUI.privacyPolicyURL; + NSUInteger TOSURLStringLength = TOSURL.absoluteString.length; + NSUInteger privacyPolicyURLStringLength = privacyPolicyURL.absoluteString.length; + + if (!TOSURLStringLength && !privacyPolicyURLStringLength) { + return nil; + } + if (!TOSURLStringLength || !privacyPolicyURLStringLength) { + NSLog(@"The terms of service and privacy policy URLs for your app must be provided together. Pl" + "ease set the terms of service policy using [FUIAuth defaultAuthUI].TOSURL and the privacy" + " policy URL using [FUIAuth defaultAuthUI].privacyPolicyURL"); + return nil; + } + NSString *termsOfServiceString = FUILocalizedString(kStr_TermsOfService); + NSString *privacyPolicyString = FUILocalizedString(kStr_PrivacyPolicy); + NSString *privacyPolicyAndTOSString = + [NSString stringWithFormat:format, termsOfServiceString, privacyPolicyString]; + NSMutableAttributedString *attributedLinkText = nil; + + if (@available(iOS 13.0, *)) { + attributedLinkText = [[NSMutableAttributedString alloc] initWithString:privacyPolicyAndTOSString + attributes:@{NSForegroundColorAttributeName: [UIColor labelColor]}]; + } else { + attributedLinkText = [[NSMutableAttributedString alloc] initWithString:privacyPolicyAndTOSString]; + } + + NSRange TOSRange = [privacyPolicyAndTOSString rangeOfString:termsOfServiceString]; + if (TOSRange.length) { + [attributedLinkText addAttribute:NSLinkAttributeName value:TOSURL range:TOSRange]; + } + + NSRange privacyPolicyRange = [privacyPolicyAndTOSString rangeOfString:privacyPolicyString]; + if (privacyPolicyRange.length) { + [attributedLinkText addAttribute:NSLinkAttributeName + value:privacyPolicyURL + range:privacyPolicyRange]; + } + return attributedLinkText; +} + +#pragma mark - Private + +- (NSAttributedString *)fullPrivacyPolicyAndTOSMessage { + return [self privacyPolicyAndTOSMessageFromFormat:FUILocalizedString(kStr_TermsOfServiceMessage)]; +} + +- (NSAttributedString *)footerPrivacyPolicyAndTOSMessage { + return [self privacyPolicyAndTOSMessageFromFormat:@"%@ %@"]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.h new file mode 100644 index 00000000..333f60ee --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.h @@ -0,0 +1,98 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FUIAuthBaseViewController.h" +#import "FUIStaticContentTableViewManager.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @class FUIStaticContentTableViewController + @brief The view controller which presents contents of @c FUIStaticContentTableViewContent. + controller has footer and header views. + */ +@interface FUIStaticContentTableViewController : FUIAuthBaseViewController + +/** @fn initWithContents:nextTitle:nextAction + @brief Convenience initializer. View controller doesn't have header and footer sections. + @param contents The contents of the table view presented in the controller. + @param nextTitle Text displayed on the navigation bar title. + @param nextAction Action triggered on the right bar item of @C UINavigationController + */ +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)nextTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction; + +// TODO: set nextAction param last arg +/** @fn initWithContents:nextTitle:nextAction:headerText: + @brief Convenience initializer. View controller doesn't have footer section. + @param contents The contents of the table view presented in the controller. + @param nextTitle Text displayed on the navigation bar title. + @param nextAction Action triggered on the right bar item of @C UINavigationController + @param headerText Text displayed at the header view controller. + */ +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)nextTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction + headerText:(nullable NSString *)headerText; + +/** @fn initWithContents:nextTitle:nextAction:headerText:footerText:footerAction: + @brief Designated initializer. + @param contents The contents of the table view presented in the controller. + @param actionTitle Text displayed on the navigation bar title. + @param nextAction Action triggered on the right bar item of @C UINavigationController + @param headerText Text displayed at the header view controller. + @param footerText Text displayed at the footer of view controller. + @param footerAction Action triggered when user taps on the footer. + */ +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)actionTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction + headerText:(nullable NSString *)headerText + footerText:(nullable NSString *)footerText + footerAction:(nullable FUIStaticContentTableViewCellAction)footerAction + NS_DESIGNATED_INITIALIZER; + +/** @fn init + @brief Please use @c initWithContents:nextTitle:nextAction:headerText:footerText:footerAction:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithNibName:bundle: + @brief Please use @c initWithContents:nextTitle:nextAction:headerText:footerText:footerAction:. + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil + bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE; + +/** @fn initWithCoder: + @brief Please use @c initWithContents:nextTitle:nextAction:headerText:footerText:footerAction:. + */ +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; + +/** @fn initWithNibName:bundle:authUI: + @brief Please use @c initWithContents:nextTitle:nextAction:headerText:footerText:footerAction:. + @param nibNameOrNil The name of the nib file to associate with the view controller. + @param nibBundleOrNil The bundle in which to search for the nib file. + @param authUI The @c FUIAuth instance that manages this view controller. + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil + bundle:(nullable NSBundle *)nibBundleOrNil + authUI:(FUIAuth *)authUI NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.m new file mode 100644 index 00000000..93f0a631 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.m @@ -0,0 +1,137 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIStaticContentTableViewController.h" + +#import "FUIAuth.h" +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kSaveButtonAccessibilityID + @brief The Accessibility Identifier for the @c next button. + */ +static NSString *const kNextButtonAccessibilityID = @"NextButtonAccessibilityID"; + +@interface FUIStaticContentTableViewController () +{ + NSString *_headerText; + NSString *_footerText; + NSString *_actionTitle; + __weak IBOutlet UILabel *_headerLabel; + __weak IBOutlet UITableView *_tableView; + __weak IBOutlet UIButton *_footerButton; + FUIStaticContentTableViewManager *_tableViewManager; + FUIStaticContentTableViewCellAction _nextAction; + FUIStaticContentTableViewCellAction _footerAction; +} +@end + +@implementation FUIStaticContentTableViewController + +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)nextTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction { + return [self initWithContents:contents nextTitle:nextTitle nextAction:nextAction headerText:nil]; +} + +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)nextTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction + headerText:(nullable NSString *)headerText { + return [self initWithContents:contents + nextTitle:nextTitle + nextAction:nextAction + headerText:headerText + footerText:nil + footerAction:nil]; +} + +- (instancetype)initWithContents:(nullable FUIStaticContentTableViewContent *)contents + nextTitle:(nullable NSString *)actionTitle + nextAction:(nullable FUIStaticContentTableViewCellAction)nextAction + headerText:(nullable NSString *)headerText + footerText:(nullable NSString *)footerText + footerAction:(nullable FUIStaticContentTableViewCellAction)footerAction { + if (self = [super initWithNibName:NSStringFromClass([self class]) + bundle:[FUIAuthUtils bundleNamed:FUIAuthBundleName] + authUI:[FUIAuth defaultAuthUI]]) { + _tableViewManager.contents = contents; + _nextAction = [nextAction copy]; + _footerAction = [footerAction copy]; + _headerText = [headerText copy]; + _footerText = [footerText copy]; + _actionTitle = [actionTitle copy]; + + UIBarButtonItem *actionButtonItem = + [FUIAuthBaseViewController barItemWithTitle:_actionTitle + target:self + action:@selector(onNext)]; + actionButtonItem.accessibilityIdentifier = kNextButtonAccessibilityID; + self.navigationItem.rightBarButtonItem = actionButtonItem; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _tableViewManager = [[FUIStaticContentTableViewManager alloc] init]; + _tableViewManager.tableView = _tableView; + _tableView.delegate = _tableViewManager; + _tableView.dataSource = _tableViewManager; + if (_headerText) { + _headerLabel.text = _headerText; + } else { + _tableView.tableHeaderView = nil; + } + if (!_footerText) { + _tableView.tableFooterView.hidden = YES; + } else { + [_footerButton setTitle:_footerText forState:UIControlStateNormal]; + } + + [self enableDynamicCellHeightForTableView:_tableView]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [self updateHeaderSize]; +} + +- (void)updateHeaderSize { + _headerLabel.preferredMaxLayoutWidth = _headerLabel.bounds.size.width; + CGFloat height = [_tableView.tableHeaderView + systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; + CGRect frame = _tableView.tableHeaderView.frame; + frame.size.height = height; + _tableView.tableHeaderView.frame = frame; +} + +- (void)onNext { + if (_nextAction) { + _nextAction(); + } +} +- (IBAction)onFooterAction:(id)sender { + if (_footerAction) { + _footerAction(); + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.xib b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.xib new file mode 100644 index 00000000..04a2b42b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewController.xib @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.h new file mode 100644 index 00000000..fe0df2cc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.h @@ -0,0 +1,311 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#pragma mark - Forward Declarations + +@class FUIStaticContentTableViewCell; +@class FUIStaticContentTableViewContent; +@class FUIStaticContentTableViewSection; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Block Type Definitions + +/** @typedef FUIStaticContentTableViewCellAction + @brief The type of block invoked when a cell is tapped. + */ +typedef void(^FUIStaticContentTableViewCellAction)(void); + +#pragma mark - + +/** @class FUIStaticContentTableViewManager + @brief Generic class useful for populating a @c UITableView with static content. + */ +@interface FUIStaticContentTableViewManager : NSObject + +/** @property contents + @brief The static contents of the @c UITableView. + @remarks Setting this property will reload the @c UITableView. + */ +@property(nonatomic, strong, nullable) FUIStaticContentTableViewContent *contents; + +/** @property tableView + @brief A reference to the managed @c UITableView. + @remarks This is needed to automatically reload the table view when the @c contents are changed. + */ +@property(nonatomic, weak, nullable) IBOutlet UITableView *tableView; + +@end + +#pragma mark - + +/** @class FUIStaticContentTableViewContent + @brief Represents the contents of a @c UITableView. + */ +@interface FUIStaticContentTableViewContent : NSObject + +/** @property sections + @brief The sections for the @c UITableView. + */ +@property(nonatomic, copy, readonly, nullable) + NSArray *sections; + +/** @fn contentWithSections: + @brief Convenience factory method for creating a new instance of + @c FUIStaticContentTableViewContent. + @param sections The sections for the @c UITableView. + */ ++ (instancetype)contentWithSections:(nullable NSArray *)sections; + +/** @fn init + @brief Please use initWithSections: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithSections: + @brief Designated initializer. + @param sections The sections in the @c UITableView. + */ +- (instancetype)initWithSections:(nullable NSArray *)sections; + +@end + +#pragma mark - + +/** @class FUIStaticContentTableViewSection + @brief Represents a section in a @c UITableView. + @remarks Each section has a title (used for the section title in the @c UITableView) and an + array of cells. + */ +@interface FUIStaticContentTableViewSection : NSObject + +/** @property title + @brief The title of the section in the @c UITableView. + */ +@property(nonatomic, copy, readonly, nullable) NSString *title; + +/** @property cells + @brief The cells in this section of the @c UITableView. + */ +@property(nonatomic, copy, readonly, nullable) NSArray *cells; + +/** @fn sectionWithTitle:cells: + @brief Convenience factory method for creating a new instance of + @c FUIStaticContentTableViewSection. + @param title The title of the section in the @c UITableView. + @param cells The cells in this section of the @c UITableView. + */ ++ (instancetype) sectionWithTitle:(nullable NSString *)title + cells:(nullable NSArray *)cells; + +/** @fn init + @brief Please use initWithTitle:cells: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** @fn initWithTitle:cells: + @brief Designated initializer. + @param title The title of the section in the @c UITableView. + @param cells The cells in this section of the @c UITableView. + */ +- (instancetype)initWithTitle:(nullable NSString *)title + cells:(nullable NSArray *)cells; + +@end + +#pragma mark - + +/** @typedef FUIStaticContentTableViewCellType + @brief Defines all possible styles of @c FUIStaticContentTableViewCell. + */ +typedef NS_ENUM(NSInteger, FUIStaticContentTableViewCellType) { + FUIStaticContentTableViewCellTypeDefault = 0, + FUIStaticContentTableViewCellTypeButton, + FUIStaticContentTableViewCellTypeInput, + FUIStaticContentTableViewCellTypePassword +}; + +/** @class FUIStaticContentTableViewCell + @brief Represents a cell in a @c UITableView. + */ +@interface FUIStaticContentTableViewCell : NSObject + +/** @property title + @brief The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + */ +@property(nonatomic, copy, readonly, nullable) NSString *title; + +/** @property value + @brief The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + */ +@property(nonatomic, copy, nullable) NSString *value; + +/** @property placeholder + @brief The text of the placeholder or hint of the @c FUIStaticContentTableViewCell. + */ +@property(nonatomic, copy, nullable) NSString *placeholder; + +/** @property type + @brief Style of displaying cell. Default value is @c FUIStaticContentTableViewCellTypeDefault + */ +@property(nonatomic, assign) FUIStaticContentTableViewCellType type; + +/** @property action + @brief A block which is executed when the cell is selected. + @remarks Avoid retain cycles. Since these blocked are retained here, and your + @c UIViewController's object graph likely retains this object, you don't want these blocks + to retain your @c UIViewController. The easiest thing is just to create a weak reference to + your @c UIViewController and pass it a message as the only thing the block does. + */ +@property(nonatomic, copy, readonly, nullable) FUIStaticContentTableViewCellAction action; + +/** @fn cellWithTitle: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title; + +/** @fn cellWithTitle:value: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param value The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value; + +/** @fn cellWithTitle:action: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param action A block which is executed when the cell is selected. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + action:(nullable FUIStaticContentTableViewCellAction)action; + +/** @fn cellWithTitle:action:type: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param type Style of displaying cell. + @param action A block which is executed when the cell is selected. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action; + +/** @fn cellWithTitle:value:action: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param value The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + @param action A block which is executed when the cell is selected. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + action:(nullable FUIStaticContentTableViewCellAction)action; + +/** @fn cellWithTitle:value:type:action: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param value The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + @param type Style of displaying cell. + @param action A block which is executed when the cell is selected. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action; + +/** @fn cellWithTitle:value:type:action: + @brief Convenience factory method for a new instance of @c FUIStaticContentTableViewCell. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param value The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + @param placeholder The placeholder of input filed, if any. + @param action A block which is executed when the cell is selected. + @param type Style of displaying cell. + */ ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + placeholder:(nullable NSString *)placeholder + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action; + +/** @fn initWithTitle:value:action:type: + @brief Designated initializer. + @param title The text of the @c titleLabel of the @c FUIStaticContentTableViewCell. + @param value The text of the @c detailTextLabel of the @c FUIStaticContentTableViewCell. + @param placeholder The placeholder of input filed, if any. + @param type Style of displaying cell. + @param action A block which is executed when the cell is selected. + */ +- (instancetype)initWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + placeholder:(nullable NSString *)placeholder + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action + NS_DESIGNATED_INITIALIZER; + +/** @fn init + @brief Please use initWithTitle:value:action:type: + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +/** @class FUIPasswordTableViewCell + @brief Represents a cell in a @c UITableView. This cell has password input field. + */ +@interface FUIPasswordTableViewCell : UITableViewCell + +/** @var cellData + @brief Used to retrieve modified value of the cell. + */ +@property (nonatomic) FUIStaticContentTableViewCell *cellData; + +/** @var title + @brief The title label of the cell. + */ +@property (weak, nonatomic) IBOutlet UILabel *title; + +/** @var password + @brief The password inout field of the cell. + */ +@property (weak, nonatomic) IBOutlet UITextField *password; + +@end + +/** @class FUIInputTableViewCell + @brief Represents a cell in a @c UITableView. This cell has regular input field. + */ +@interface FUIInputTableViewCell : UITableViewCell + +/** @var cellData + @brief Used to retrieve modified value of the cell. + */ +@property (nonatomic) FUIStaticContentTableViewCell *cellData; + +/** @var title + @brief The title label of the cell. + */ +@property (weak, nonatomic) IBOutlet UILabel *title; + +/** @var password + @brief The inout field of the cell. + */ +@property (weak, nonatomic) IBOutlet UITextField *input; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.m b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.m new file mode 100644 index 00000000..56dc4f48 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.m @@ -0,0 +1,319 @@ +// +// Copyright (c) 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIStaticContentTableViewManager.h" + +#import "FUIAuthUtils.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kCellReuseIdentitfier + @brief The reuse identifier for default style table view cell. + */ +static NSString *const kCellReuseIdentitfier = @"reuseIdentifier"; + +/** @var kValueCellReuseIdentitfier + @brief The reuse identifier for value style table view cell. + */ +static NSString *const kValueCellReuseIdentitfier = @"reuseValueIdentifier"; + +/** @var kPasswordCellReuseIdentitfier + @brief The reuse identifier for password style table view cell. + */ +static NSString *const kPasswordCellReuseIdentitfier = @"passwordCellReuseIdentitfier"; + +/** @var kInputCellReuseIdentitfier + @brief The reuse identifier for input style table view cell. + */ +static NSString *const kInputCellReuseIdentitfier = @"inputCellReuseIdentitfier"; + +/** @var kVisibilityOffImage + @brief Name of icon to show current password in secure input field. + */ +static NSString *const kVisibilityOffImage = @"ic_visibility_off.png"; + +/** @var kVisibilityOnImage + @brief Name of icon to show current password in secure input field. + */ +static NSString *const kVisibilityOnImage = @"ic_visibility.png"; + +#pragma mark - + +@implementation FUIStaticContentTableViewManager + +- (void)setContents:(nullable FUIStaticContentTableViewContent *)contents { + _contents = contents; + [self.tableView reloadData]; +} + +- (void)setTableView:(nullable UITableView *)tableView { + _tableView = tableView; + [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kCellReuseIdentitfier]; + + UINib *passwordCellNib = [UINib nibWithNibName:NSStringFromClass([FUIPasswordTableViewCell class]) + bundle:[FUIAuthUtils bundleNamed:FUIAuthBundleName]]; + [tableView registerNib:passwordCellNib forCellReuseIdentifier:kPasswordCellReuseIdentitfier]; + + UINib *inputCellNib = [UINib nibWithNibName:NSStringFromClass([FUIInputTableViewCell class]) + bundle:[FUIAuthUtils bundleNamed:FUIAuthBundleName]]; + [tableView registerNib:inputCellNib forCellReuseIdentifier:kInputCellReuseIdentitfier]; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return _contents.sections.count; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _contents.sections[section].cells.count; +} + +- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + return _contents.sections[section].title; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + FUIStaticContentTableViewCell *cellData = + _contents.sections[indexPath.section].cells[indexPath.row]; + UITableViewCell *cell; + if (cellData.type == FUIStaticContentTableViewCellTypePassword) { + return [self dequeuePasswordCell:cellData tableView:tableView]; + } else if (cellData.type == FUIStaticContentTableViewCellTypeInput) { + return [self dequeueInputCell:cellData tableView:tableView]; + } else if (cellData.value.length) { + cell = [tableView dequeueReusableCellWithIdentifier:kValueCellReuseIdentitfier]; + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 + reuseIdentifier:kValueCellReuseIdentitfier]; + cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; + cell.detailTextLabel.minimumScaleFactor = 0.5; + } + } else { + // kCellReuseIdentitfier has already been registered. + cell = [tableView dequeueReusableCellWithIdentifier:kCellReuseIdentitfier + forIndexPath:indexPath]; + } + cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + cell.detailTextLabel.text = cellData.value; + cell.textLabel.text = cellData.title; + cell.accessoryType = cellData.action && + cellData.type == FUIStaticContentTableViewCellTypeDefault ? + UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; + cell.textLabel.textColor = cellData.type == FUIStaticContentTableViewCellTypeButton ? + [UIColor blueColor] : [UIColor blackColor]; + cell.selectionStyle = cellData.action ? UITableViewCellSelectionStyleDefault : + UITableViewCellSelectionStyleNone; + return cell; +} + +- (UITableViewCell *)dequeuePasswordCell:(FUIStaticContentTableViewCell *)cellData + tableView:(UITableView *)tableView{ + FUIPasswordTableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:kPasswordCellReuseIdentitfier]; + cell.title.text = cellData.title; + cell.password.text = cellData.value; + cell.password.placeholder = cellData.placeholder; + cell.cellData = cellData; + cell.title.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + return cell; +} + +- (UITableViewCell *)dequeueInputCell:(FUIStaticContentTableViewCell *)cellData + tableView:(UITableView *)tableView{ + FUIInputTableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:kInputCellReuseIdentitfier]; + cell.title.text = cellData.title; + cell.input.text = cellData.value; + cell.input.placeholder = cellData.placeholder; + cell.cellData = cellData; + cell.title.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + return cell; +} + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + FUIStaticContentTableViewCell *cellData = + _contents.sections[indexPath.section].cells[indexPath.row]; + BOOL hasAssociatedAction = cellData.action != nil; + if (hasAssociatedAction) { + cellData.action(); + } + [tableView deselectRowAtIndexPath:indexPath animated:hasAssociatedAction]; +} + +@end + +#pragma mark - + +@implementation FUIStaticContentTableViewContent + ++ (instancetype)contentWithSections: + (nullable NSArray *)sections { + return [[self alloc] initWithSections:sections]; +} + +- (instancetype)initWithSections:(nullable NSArray *)sections { + self = [super init]; + if (self) { + _sections = [sections copy]; + } + return self; +} + +@end + +#pragma mark - + +@implementation FUIStaticContentTableViewSection + ++ (instancetype)sectionWithTitle:(nullable NSString *)title + cells:(nullable NSArray *)cells { + return [[self alloc] initWithTitle:title cells:cells]; +} + +- (instancetype)initWithTitle:(nullable NSString *)title + cells:(nullable NSArray *)cells { + self = [super init]; + if (self) { + _title = [title copy]; + _cells = [cells copy]; + } + return self; +} + +@end + +#pragma mark - + +@implementation FUIStaticContentTableViewCell + ++ (instancetype)cellWithTitle:(nullable NSString *)title { + return [[self alloc] initWithTitle:title + value:nil + placeholder:nil + type:FUIStaticContentTableViewCellTypeDefault + action:nil]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value { + return [[self alloc] initWithTitle:title + value:value + placeholder:nil + type:FUIStaticContentTableViewCellTypeDefault + action:nil]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + action:(nullable FUIStaticContentTableViewCellAction)action { + return [[self alloc] initWithTitle:title + value:nil + placeholder:nil + type:FUIStaticContentTableViewCellTypeDefault + action:action]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action { + return [[self alloc] initWithTitle:title + value:nil + placeholder:nil + type:type + action:action]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + action:(nullable FUIStaticContentTableViewCellAction)action { + return [[self alloc] initWithTitle:title + value:value + placeholder:nil + type:FUIStaticContentTableViewCellTypeDefault + action:action]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action { + return [[self alloc] initWithTitle:title + value:value + placeholder:nil + type:type + action:action]; +} + ++ (instancetype)cellWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + placeholder:(nullable NSString *)placeholder + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action { + return [[self alloc] initWithTitle:title + value:value + placeholder:placeholder + type:type + action:action]; +} + +- (instancetype)initWithTitle:(nullable NSString *)title + value:(nullable NSString *)value + placeholder:(nullable NSString *)placeholder + type:(FUIStaticContentTableViewCellType) type + action:(nullable FUIStaticContentTableViewCellAction)action { + self = [super init]; + if (self) { + _title = [title copy]; + _value = [value copy]; + _action = [action copy]; + _placeholder = [placeholder copy]; + _type = type; + } + return self; +} + +@end + +@interface FUIPasswordTableViewCell () +@property (weak, nonatomic) IBOutlet UIButton *visibilityButton; +@end + +@implementation FUIPasswordTableViewCell + +- (IBAction)onPasswordVisibilitySelected:(id)sender { + self.password.secureTextEntry = ! self.password.secureTextEntry; + UIImage *image = self.password.secureTextEntry ? [UIImage imageNamed:kVisibilityOnImage] + : [UIImage imageNamed:kVisibilityOffImage]; + [self.visibilityButton setImage:image forState:UIControlStateNormal]; +} +- (IBAction)onPasswordChanged:(id)sender { + self.cellData.value = self.password.text; +} + +@end + +@implementation FUIInputTableViewCell + +- (IBAction)onInputChanged:(id)sender { + self.cellData.value = self.input.text; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FirebaseAuthUI.h b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FirebaseAuthUI.h new file mode 100644 index 00000000..913b88f1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/FirebaseAuthUI.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@import UIKit; + +//! Project version number for FirebaseAuthUI. +FOUNDATION_EXPORT double FirebaseAuthUIVersionNumber; + +//! Project version string for FirebaseAuthUI. +FOUNDATION_EXPORT const unsigned char FirebaseAuthUIVersionString[]; + + +#import "FUIAccountSettingsOperationType.h" +#import "FUIAccountSettingsViewController.h" + +#import "FUIAuth.h" +#import "FUIAuthBaseViewController.h" +#import "FUIAuthErrorUtils.h" +#import "FUIAuthPickerViewController.h" +#import "FUIAuthProvider.h" +#import "FUIAuthUtils.h" +#import "FUIAuthStrings.h" +#import "FUIPrivacyAndTermsOfServiceView.h" +#import "FUIAuthTableViewCell.h" +#import "FUIAuthTableHeaderView.h" diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle.png new file mode 100755 index 00000000..93082c33 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle2x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle2x.png new file mode 100755 index 00000000..ea280fe6 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle2x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle3x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle3x.png new file mode 100755 index 00000000..5d488d08 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_account_circle3x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility.png new file mode 100644 index 00000000..58597e91 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@2x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@2x.png new file mode 100644 index 00000000..1f7b4cc8 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@2x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@3x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@3x.png new file mode 100644 index 00000000..c816ab49 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility@3x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off.png new file mode 100644 index 00000000..3efdf492 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@2x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@2x.png new file mode 100644 index 00000000..46bf0c93 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@2x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@3x.png b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@3x.png new file mode 100644 index 00000000..13eb65df Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Resources/ic_visibility_off@3x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ar.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ar.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..86c2a466 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ar.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "مرحبًا"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "تسجيل الدخول عبر البريد الإلكتروني"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "إدخال عنوان بريدك الإلكتروني"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "إنّ عنوان البريد الإلكتروني هذا غير صحيح."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "لا يتيح هذا التطبيق استخدام هذا النوع من الحساب"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "لديك حساب حاليًا"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "سبق أن استخدمت %@. يُرجى تسجيل الدخول باسم %@ للمتابعة."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "تسجيل الدخول"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "إدخال كلمة المرور"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "لا يمكن أن يكون حقل كلمة المرور فارغًا."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "إنّ البريد الإلكتروني وكلمة المرور اللذين أدخلتهما ليسا متطابقين."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "لا يتطابق عنوان البريد الإلكتروني هذا مع حساب حالي."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "إنّ عنوان البريد الإلكتروني هذا تابع لحساب سبق أن تم إيقافه."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "لقد أدخلت كلمة مرور غير صحيحة لمرات كثيرة جدًا. يُرجى المحاولة مجددًا بعد بضع دقائق."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "تعذّر الحصول على مزوّد %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "لا تتطابق رسالتا البريد الإلكتروني"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "استرداد كلمة المرور"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "تم إرسال تعليمات إلى البريد الإلكتروني هذا تشرح كيفية إعادة تعيين كلمة المرور."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "إثبات ملكية بريدك الإلكتروني"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "اتبع التعليمات التي تم إرسالها إلى %@ لاسترداد كلمة المرور."; + +/* Title for sign up screen. */ +"SignUpTitle" = "إنشاء حساب"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "الاسم الأول واسم العائلة"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "اختيار كلمة المرور"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "بنود الخدمة"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "سياسة الخصوصية"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "تشير المتابعة إلى موافقتك على %@ و%@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "يستخدم حساب آخر عنوان البريد الإلكتروني."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "تتضمن كلمات المرور القوية 6 أرقام على الأقل ومزيجًا من الأحرف والأرقام."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "ثمة عدد كبير جدًا من الطلبات الواردة من عنوان IP التابع لك. يُرجى المحاولة مجددًا بعد بضع دقائق."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "لقد سبق أن استخدمت %@ لتسجيل الدخول. يُرجى إدخال كلمة المرور لهذا الحساب."; + +/* OK button title. */ +"OK" = "موافق"; + +/* Cancel button title. */ +"Cancel" = "إلغاء"; + +/* Back button title. */ +"Back" = "رجوع"; + +/* Next button title. */ +"Next" = "التالي"; + +/* Save button title. */ +"Save" = "حفظ"; + +/* Send button title. */ +"Send" = "إرسال"; + +/* Resend button title. */ +"Resend" = "إعادة إرسال الرسالة"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "البريد الإلكتروني"; + +/* Label next to a password text field. */ +"Password" = "كلمة المرور"; + +/* Label next to a name text field. */ +"Name" = "الاسم"; + +/* Alert title Error. */ +"Error" = "خطأ"; + +/* Alert button title Close. */ +"Close" = "إغلاق"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "الملف الشخصي"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "الأمان"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "الحسابات المرتبطة"; + +/* Account Settings cell title Name. */ +"AS_Name" = "الاسم"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "البريد الإلكتروني"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "إضافة كلمة مرور"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "تغيير كلمة المرور"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "تسجيل الخروج"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "حذف الحساب"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "هل نسيت كلمة المرور؟"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "تأكيد ملكية الحساب"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "هل تريد حذف الحساب؟"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "سيؤدي هذا الإجراء إلى حذف كل البيانات المقترنة بحسابك ولا يمكن التراجع عنه. يجب تسجيل الدخول مجددًا لإكمال هذا الإجراء"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "سيؤدي هذا الإجراء إلى حذف كل البيانات المقترنة بحسابك ولا يمكن التراجع عنه. هل تريد بالتأكيد حذف حسابك؟"; + +/* Text of Delete action button. */ +"Delete" = "حذف"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "حذف الحساب"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "لا يمكن التراجع عن هذا الإجراء"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "إلغاء الربط"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "حساب مرتبط"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "هل تريد إلغاء ربط الحساب؟"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "لن تتمكن بعد الآن من تسجيل الدخول باستخدام حسابك"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "إلغاء ربط الحساب"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "لتغيير عنوان البريد الإلكتروني المقترن بحسابك، سيلزمك تسجيل الدخول مرة أخرى."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "لتغيير كلمة المرور، يجب أولاً إدخال كلمة المرور الحالية."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "تعديل الرسالة"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "تعديل الاسم"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "لإضافة كلمة مرور إلى حسابك، يجب تسجيل الدخول من جديد."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "لتغيير كلمة المرور في حسابك، يجب تسجيل الدخول من جديد."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "لتغيير كلمة المرور، يجب أولاً إدخال كلمة المرور الحالية."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "إضافة كلمة مرور"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "تغيير كلمة المرور"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "البريد الإلكتروني"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "تسجيل الدخول عبر %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "إدخال اسمك"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "إدخال عنوان بريدك الإلكتروني"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "إدخال كلمة المرور"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "كلمة المرور الجديدة"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "اختيار كلمة المرور"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "هل تواجه مشكلة في تسجيل الدخول؟"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "تأكيد عنوان البريد الإلكتروني"; + +/* Title of successfully signed in label. */ +"SignedIn" = "تمّ تسجيل الدخول."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "هل تواجه مشكلة في استلام الرسائل الإلكترونية؟"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "يمكنك تجربة الحلول الشائعة التالية: \n - التأكّد ممّا إذا تمّ وضع علامة على الرسالة الإلكترونية بأنها \"غير مرغوب فيها\" أو نقلها تلقائيًا إلى مجلّد آخر\n - التحقّق من اتصال الإنترنت\n - التأكّد من كتابة عنوان البريد الإلكتروني بالشكل الصحيح\n - التأكّد من توفّر مساحة فارغة في البريد الوارد أو من عدم حدوث أي مشاكل أخرى في إعدادات البريد الوارد\n إذا لم تنجح الخطوات أعلاه، يمكنك إعادة إرسال الرسالة الإلكترونية. ستؤدي هذه الخطوة إلى إلغاء الرابط المضمّن في الرسالة السابقة."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "تمّ إرسال رسالة إلكترونية لتسجيل الدخول تتضمّن تعليمات إضافية إلى %@. يُرجى التحقق من بريدك الإلكتروني لإكمال عملية تسجيل الدخول."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "تمّ إرسال رسالة إلكترونية لتسجيل الدخول"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bg.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bg.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..7ab6fe66 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bg.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Добре дошли"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Вход с имейл"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Въвеждане на имейл адреса ви"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Този имейл адрес е неправилен."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Този тип профил не се поддържа от това приложение"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Вече имате профил"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Вече използвахте %@. За да продължите, влезте с %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Вход"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Въведете паролата си"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Трябва да въведете парола."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Имейл адресът и паролата, които въведохте, не си съответстват."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Този имейл адрес не съответства на съществуващ профил."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Този имейл адрес е за профил, който е деактивиран."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Въведохте неправилна парола твърде много пъти. Опитайте отново след няколко минути."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Не може да се намери доставчик за %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Имейл адресите не съвпадат"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Възстановяване на паролата"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "На този имейл адрес ще получите инструкции за повторно задаване на паролата."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Проверете електронната си поща"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "За да възстановите паролата си, изпълнете инструкциите, изпратени до %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Създаване на профил"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Име и фамилия"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Изберете парола"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Общите условия"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Декларация за поверителност"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Продължавайки, приемате нашите %@ и %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Имейл адресът вече се използва от друг профил."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Надеждните пароли съдържат поне 6 знака и комбинация от букви и цифри."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "От IP адреса ви се изпращат твърде много заявки за профил. Опитайте отново след няколко минути."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Вече използвахте %@ за вход. Въведете паролата си за този профил."; + +/* OK button title. */ +"OK" = "ОК"; + +/* Cancel button title. */ +"Cancel" = "Отказ"; + +/* Back button title. */ +"Back" = "Назад"; + +/* Next button title. */ +"Next" = "Напред"; + +/* Save button title. */ +"Save" = "Запазване"; + +/* Send button title. */ +"Send" = "Изпращане"; + +/* Resend button title. */ +"Resend" = "Повторно изпращане"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Имейл"; + +/* Label next to a password text field. */ +"Password" = "Парола"; + +/* Label next to a name text field. */ +"Name" = "Име"; + +/* Alert title Error. */ +"Error" = "Грешка"; + +/* Alert button title Close. */ +"Close" = "Затваряне"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Потребителски профил"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Сигурност"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Свързани профили"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Име"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Имейл"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Добавяне на парола"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Промяна на паролата"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Изход"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Изтриване на профила"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Забравили сте паролата си?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Потвърждаване на самоличността ви"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Да се изтрие ли профилът?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Това действие ще изтрие всички свързани с профила ви данни и не може да се отмени. За да го завършите, ще трябва отново да влезете в профила"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Това действие ще изтрие всички свързани с профила ви данни и не може да се отмени. Наистина ли искате да изтриете профила?"; + +/* Text of Delete action button. */ +"Delete" = "Изтриване"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Изтриване на профила"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Това действие не може да се отмени"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Прекратяване на връзката"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Свързан профил"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Да се прекрати ли връзката с профила?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Вече няма да можете да влизате с профила си"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Прекратяване на връзката с профила"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "За да промените имейл адреса, свързан с профила ви, ще трябва да влезете отново."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "За да промените паролата си, първо трябва да въведете текущата."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Редактиране на имейла"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Редактиране на името"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "За да добавите парола към профила си, ще трябва да влезете отново."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "За да промените паролата за профила си, ще трябва да влезете отново."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "За да промените паролата си, първо трябва да въведете текущата."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Добавяне на парола"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Промяна на паролата"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Имейл"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Вход с %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Въведете името си"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Въведете имейла си"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Въведете паролата си"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Нова парола"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Изберете парола"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Имате проблем при влизането?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Потвърждаване на имейл адреса"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Влязохте в профила!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Имате проблеми с получаването на имейла?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Изпробвайте следните често използвани решения: \n – Проверете дали имейлът не е обозначен и филтриран като спам.\n – Проверете връзката си с интернет.\n – Проверете дали имейлът е изписан правилно.\n – Проверете дали в пощенската ви кутия има достатъчно пространство, или не е налице друг проблем с настройките й.\n Ако стъпките по-горе не разрешат проблема, можете отново да изпратите имейла. Имайте предвид, че това ще деактивира връзката в предходното съобщение."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Изпратихме имейл до %@ за вход в профила с допълнителни инструкции. Проверете входящата си поща, за да завършите процеса."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Изпратен е имейл за вход в профила"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bn.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bn.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..58426fe0 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/bn.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "স্বাগতম"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ইমেল দিয়ে সাইন-ইন করুন"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "আপনার ইমেল লিখুন"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "ইমেল অ্যাড্রেসটি সঠিক নয়।"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "এই ধরনের অ্যাকাউন্ট এই অ্যাপে ব্যবহার করা যায় না"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "আপনার আগে থেকেই একটি অ্যাকাউন্ট আছে"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "আপনি আগেই %@ ব্যবহার করেছেন। চালিয়ে যেতে %@ দিয়ে সাইন-ইন করুন।"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "সাইন-ইন করুন"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "আপনার পাসওয়ার্ডটি লিখুন"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "পাসওয়ার্ডটি খালি রাখা যাবে না।"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "আপনার দেওয়া ইমেল এবং পাসওয়ার্ডটি মিলছে না।"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "আগে থেকে থাকা অ্যাকাউন্টের সাথে ইমেল অ্যাড্রেসটি মিলছে না।"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "এই ইমেল অ্যাড্রেসটি এমন একটি অ্যাকাউন্টের জন্য যেটি অক্ষম করা হয়েছে।"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "আপনি অনেকবার ভুল পাসওয়ার্ড লিখেছেন। কিছুক্ষণের মধ্যে আবার চেষ্টা করুন।"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ এর জন্য প্রদানকারী পাওয়া যাচ্ছে না।"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ইমেলটি মেল হচ্ছে না"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "পাসওয়ার্ড পুনরুদ্ধার করুন"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "কীভাবে পাসওয়ার্ড রিসেট করবেন তা জানতে এই ইমেলে নির্দেশাবলী পাঠান।"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "আপনার ইমেল দেখুন"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "আপনার পাসওয়ার্ড পুনরুদ্ধার করতে %@ তে পাঠানো নির্দেশ অনুসরণ করুন।"; + +/* Title for sign up screen. */ +"SignUpTitle" = "অ্যাকাউন্ট তৈরি করুন"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "নাম ও পদবি"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "পাসওয়ার্ড বেছে নিন"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "পরিষেবার শর্তাবলি"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "গোপনীয়তা নীতি"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "চালিয়ে যাওয়ার অর্থ, আপনি আমাদের %@ এবং %@-এর সাথে সম্মত।"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "এই ইমেল অ্যাড্রেসটি আগে থেকেই অন্য অ্যাকাউন্টে ব্যবহার করা হচ্ছে।"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "সুরক্ষিত পাসওয়ার্ডে কমপক্ষে ৬টি বিশেষ বর্ণ এবং অক্ষর ও সংখ্যা মিশিয়ে থাকবে।"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "আপনার IP অ্যাড্রেস থেকে অনেকগুলি অ্যাকাউন্টের অনুরোধ আসছে। কিছুক্ষণের মধ্যে আবার চেষ্টা করুন।"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "সাইন-ইন করতে আপনি %@ আগেই ব্যবহার করেছেন। সেই অ্যাকাউন্টের জন্য আপনার পাসওয়ার্ড লিখুন।"; + +/* OK button title. */ +"OK" = "ঠিক আছে"; + +/* Cancel button title. */ +"Cancel" = "বাতিল করুন"; + +/* Back button title. */ +"Back" = "ফিরে যান"; + +/* Next button title. */ +"Next" = "পরবর্তী"; + +/* Save button title. */ +"Save" = "সেভ করুন"; + +/* Send button title. */ +"Send" = "পাঠান"; + +/* Resend button title. */ +"Resend" = "আবার পাঠান"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ইমেল"; + +/* Label next to a password text field. */ +"Password" = "পাসওয়ার্ড"; + +/* Label next to a name text field. */ +"Name" = "নাম"; + +/* Alert title Error. */ +"Error" = "ত্রুটি"; + +/* Alert button title Close. */ +"Close" = "বন্ধ করুন"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "প্রোফাইল"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "নিরাপত্তা"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "লিঙ্ক করা অ্যাকাউন্ট"; + +/* Account Settings cell title Name. */ +"AS_Name" = "নাম"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ইমেল"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "পাসওয়ার্ড যোগ করুন"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "পাসওয়ার্ড পরিবর্তন করুন"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "সাইন-আউট করুন"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "অ্যাকাউন্টটি মুছুন"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "পাসওয়ার্ড ভুলে গেছেন?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "আপনার পরিচয় যাচাই করুন"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "অ্যাকাউন্ট মুছবেন?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "আপনার অ্যাকাউন্টের সাথে যুক্ত সমস্ত ডেটা মুছে ফেলা হবে, এবং পূর্বাবস্থায় ফেরানো যাবে না। এই কাজটি সম্পূর্ণ করতে আপনাকে আবার সাইন-ইন করতে হবে"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "আপনার অ্যাকাউন্টের সাথে যুক্ত সমস্ত ডেটা মুছে ফেলা হবে, এবং পূর্বাবস্থায় ফেরানো যাবে না। আপনি কি অ্যাকাউন্টটি মুছে ফেলার বিষয়ে নিশ্চিত?"; + +/* Text of Delete action button. */ +"Delete" = "মুছুন"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "অ্যাকাউন্টটি মুছুন"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "এই কাজটি পূর্বাবস্থায় ফেরানো যাবে না"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "লিঙ্কমুক্ত করুন"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "লিঙ্ক করা অ্যাকাউন্ট"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "অ্যাকাউন্ট লিঙ্কমুক্ত করবেন?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "আপনি আর এই অ্যাকাউন্টটি ব্যবহার করে সাইন-ইন করতে পারবেন না"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "অ্যাকাউন্ট লিঙ্কমুক্ত করুন"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "আপনার অ্যাকাউন্টের সাথে যুক্ত ইমেল অ্যাড্রেসটি পরিবর্তন করতে আপনাকে আবার সাইন-ইন করতে হবে।"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "পাসওয়ার্ড পরিবর্তন করার জন্য আগে আপনাকে বর্তমান পাসওয়ার্ডটি লিখতে হবে।"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ইমেলটি সম্পাদনা করুন"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "নাম সম্পাদনা করুন"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "আপনার অ্যাকাউন্টে পাসওয়ার্ড যোগ করতে আপনাকে আবার সাইন-ইন করতে হবে।"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "আপনার অ্যাকাউন্টের পাসওয়ার্ড পরিবর্তন করতে আপনাকে আবার সাইন-ইন করতে হবে।"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "পাসওয়ার্ড পরিবর্তন করার জন্য আগে আপনাকে বর্তমান পাসওয়ার্ডটি লিখতে হবে।"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "পাসওয়ার্ড যোগ করুন"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "পাসওয়ার্ড পরিবর্তন করুন"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ইমেল"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ দিয়ে সাইন-ইন করুন"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "আপনার নাম লিখুন"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "আপনার ইমেল লিখুন"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "আপনার পাসওয়ার্ডটি লিখুন"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "নতুন পাসওয়ার্ড"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "পাসওয়ার্ড বেছে নিন"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "সাইন-ইন করতে সমস্যা হচ্ছে?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ইমেল আইডি কনফার্ম করুন"; + +/* Title of successfully signed in label. */ +"SignedIn" = "সাইন-ইন করা হয়েছে!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "ইমেল পেতে সমস্যা হচ্ছে?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "এই সাধারণ সমাধানগুলি ব্যবহার করে দেখুন: \n - ইমেলটি স্প্যাম অথবা ফিল্টার হিসেবে চিহ্নিত করা হয়েছে কিনা তা দেখুন।\n - ইন্টারনেট কানেকশন পরীক্ষা করে দেখুন।\n - ইমেলের সঠিক বানান লিখেছেন কিনা তা দেখুন।\n - আপনার ইনবক্সের স্পেস শেষ হয়ে গেছে কিনা বা ইনবক্সের সেটিংস সংক্রান্ত অন্যান্য সমস্যাগুলি একবার দেখে নিন।\n উপরের পদক্ষেপগুলি যদি কাজ না করে তাহলে আপনি ইমেলটি আবার পাঠাতে পারেন। মনে রাখবেন এটি করলে পুরনো ইমেলের লিঙ্কটি আর কাজ করবে না।"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "অতিরিক্ত নির্দেশাবলী সহ সাইন-ইন করার একটি ইমেল %@-এ পাঠানো হয়েছে। সাইন-ইন করার জন্য আপনার ইমেল দেখুন।"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "সাইন-ইন করার ইমেল পাঠানো হয়েছে"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ca.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ca.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..667de8a3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ca.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Et donem la benvinguda"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Inicia la sessió amb l'adreça electrònica"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Introdueix la teva adreça electrònica"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Aquesta adreça electrònica no és correcta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Aquest tipus de compte no és compatible amb l'aplicació"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ja tens un compte"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ja has utilitzat l'adreça electrònica %@. Inicia la sessió amb %@ per continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Inicia la sessió"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Introdueix la teva contrasenya"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Cal introduir una contrasenya."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "L'adreça electrònica i la contrasenya que has introduït no coincideixen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Aquesta adreça electrònica no coincideix amb cap compte."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Aquesta adreça electrònica pertany a un compte que s'ha desactivat."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Has introduït una contrasenya incorrecta massa vegades. Torna-ho a provar d'aquí a uns quants minuts."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No es pot trobar un proveïdor per a %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Les adreces electròniques no coincideixen"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recupera la contrasenya"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Rep un correu electrònic amb instruccions per restablir la contrasenya."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Comprova el correu electrònic"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Per recuperar la contrasenya, segueix les instruccions que s'han enviat a %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crea un compte"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nom i cognoms"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Tria una contrasenya"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condicions del servei"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de privadesa"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "En continuar, acceptes les nostres %@ i la nostra %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ja hi ha un altre compte que utilitza aquesta adreça electrònica."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Perquè una contrasenya sigui segura, ha de tenir com a mínim 6 caràcters i combinar lletres i números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Aquesta adreça IP està enviant massa sol·licituds per crear comptes. Torna-ho a provar d'aquí a uns quants minuts."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ja has utilitzat l'adreça electrònica %@ per iniciar la sessió. Introdueix la contrasenya d'aquest compte."; + +/* OK button title. */ +"OK" = "D'acord"; + +/* Cancel button title. */ +"Cancel" = "Cancel·la"; + +/* Back button title. */ +"Back" = "Enrere"; + +/* Next button title. */ +"Next" = "Següent"; + +/* Save button title. */ +"Save" = "Desa"; + +/* Send button title. */ +"Send" = "Envia"; + +/* Resend button title. */ +"Resend" = "Torna a enviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adreça electrònica"; + +/* Label next to a password text field. */ +"Password" = "Contrasenya"; + +/* Label next to a name text field. */ +"Name" = "Nom"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Tanca"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguretat"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Comptes enllaçats"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nom"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adreça electrònica"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Afegeix una contrasenya"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Canvia la contrasenya"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Tanca la sessió"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Suprimeix el compte"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Has oblidat la contrasenya?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica la teva identitat"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Vols suprimir el compte?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Aquesta acció esborrarà totes les dades associades a aquest compte i no es pot desfer. Per completar-la, has de tornar a iniciar la sessió."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Aquesta acció esborrarà totes les dades associades a aquest compte i no es pot desfer. Confirmes que vols suprimir el compte?"; + +/* Text of Delete action button. */ +"Delete" = "Suprimeix"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Suprimeix el compte"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Aquesta acció no es pot desfer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desenllaça"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Compte enllaçat"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Vols desenllaçar el compte?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ja no podràs iniciar la sessió amb el teu compte"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desenllaça el compte"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Per canviar l'adreça electrònica associada al teu compte, has de tornar a iniciar la sessió."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Per canviar la contrasenya, primer has d'introduir la teva contrasenya actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edita l'adreça electrònica"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edita el nom"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Per afegir una contrasenya al teu compte, has de tornar a iniciar la sessió."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Per canviar la contrasenya del teu compte, has de tornar a iniciar la sessió."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Per canviar la contrasenya, primer has d'introduir la teva contrasenya actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Afegeix una contrasenya"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Canvia la contrasenya"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adreça electrònica"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Inicia la sessió amb %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Introdueix el teu nom"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Introdueix la teva adreça electrònica"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Introdueix la teva contrasenya"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Contrasenya nova"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Tria una contrasenya"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "No pots iniciar la sessió?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirma l'adreça electrònica"; + +/* Title of successfully signed in label. */ +"SignedIn" = "S'ha iniciat la sessió"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Tens problemes per rebre correus electrònics?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prova aquestes solucions habituals: \n - Comprova si el correu electrònic s'ha marcat com a correu brossa o s'ha filtrat.\n - Comprova la connexió a Internet.\n - Comprova que hagis escrit correctament la teva adreça electrònica.\n - Comprova que tinguis espai a la safata d'entrada i altres problemes relacionats amb la configuració de la safata d'entrada.\n - Si els passos anteriors no t'han servit d'ajuda, pots tornar a enviar el correu electrònic. Tingues en compte que l'enllaç del correu anterior es desactivarà."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "S'ha enviat un correu electrònic d'inici de sessió amb més instruccions a %@. Comprova si l'has rebut per completar l'inici de sessió."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "S'ha enviat el correu electrònic d'inici de sessió"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/cs.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/cs.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..0b6964b5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/cs.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Vítáme vás"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Přihlásit se pomocí e-mailu"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Zadejte e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-mailová adresa není správná."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Tento typ účtu aplikace nepodporuje."; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Již máte účet."; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Již jste použili službu %@. Chcete-li pokračovat, přihlaste se prostřednictvím služby %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Přihlásit se"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Zadejte své heslo"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Pole hesla nesmí být prázdné."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Zadaný e-mail a heslo se neshodují."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-mailová adresa neodpovídá žádnému stávajícímu účtu."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-mailová adresa patří k účtu, který byl zablokován."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Provedli jste příliš mnoho neplatných pokusů o zadání hesla. Opakujte akci za chvíli."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nepodařilo se nalézt poskytovatele pro službu %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-mailové adresy se neshodují"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Obnovit heslo"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Na tento e-mail vám zašleme pokyny, jak heslo obnovit."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Zkontrolujte svůj e-mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Postupujte podle pokynů odeslaných na adresu %@ a obnovte heslo."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Vytvořit účet"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Jméno a příjmení"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Heslo"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Smluvní podmínky"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Zásady ochrany soukromí"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Pokračováním vyjadřujete svůj souhlas s těmito dokumenty: %@ a %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Tuto e-mailovou adresu již využívá jiný účet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Silné heslo má alespoň šest znaků a skládá se z kombinace písmen a číslic."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Z vaší adresy IP přichází příliš mnoho požadavků na účet. Zkuste to znovu za několik minut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "K přihlášení jste již použili adresu %@. Zadejte příslušné heslo k účtu."; + +/* OK button title. */ +"OK" = "V pořádku"; + +/* Cancel button title. */ +"Cancel" = "Zrušit"; + +/* Back button title. */ +"Back" = "Zpět"; + +/* Next button title. */ +"Next" = "Další"; + +/* Save button title. */ +"Save" = "Uložit"; + +/* Send button title. */ +"Send" = "Odeslat"; + +/* Resend button title. */ +"Resend" = "Odeslat znovu"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Heslo"; + +/* Label next to a name text field. */ +"Name" = "Jméno"; + +/* Alert title Error. */ +"Error" = "Chyba"; + +/* Alert button title Close. */ +"Close" = "Zavřít"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Zabezpečení"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Propojené účty"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Jméno"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Přidat heslo"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Změnit heslo"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Odhlásit se"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Smazat účet"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Zapomněli jste heslo?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Ověřte svou identitu"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Smazat účet?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Dojde k odstranění všech údajů souvisejících s vaším účtem. Tuto akci nebude možné vrátit zpět. Pokud ji chcete skutečně provést, musíte se znovu přihlásit."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Dojde k odstranění všech údajů souvisejících s vaším účtem. Tuto akci nebude možné vrátit zpět. Opravdu chcete účet smazat?"; + +/* Text of Delete action button. */ +"Delete" = "Smazat"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Smazat účet"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tuto akci nelze vrátit zpět."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Odpojit"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Propojený účet"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Odpojit účet?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Prostřednictvím tohoto účtu už se nebudete moci přihlásit."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Odpojit účet"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Chcete-li změnit e-mailovou adresu přidruženou k vašemu účtu, musíte se znovu přihlásit."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Chcete-li změnit heslo, musíte nejprve zadat aktuální heslo."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Změnit e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Změnit jméno"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Chcete-li do účtu přidat heslo, musíte se znovu přihlásit."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Chcete-li změnit heslo k účtu, musíte se znovu přihlásit."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Chcete-li změnit heslo, musíte nejprve zadat aktuální heslo."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Přidat heslo"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Změnit heslo"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Přihlásit se přes %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Zadejte své jméno"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Zadejte e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Zadejte své heslo"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nové heslo"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Zvolte heslo."; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Máte potíže s přihlášením?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potvrzení·e-mailu"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Jste přihlášeni!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Nepřišly vám e-maily?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Vyzkoušejte tato běžná řešení: \n – Zkontrolujte, jestli e-mail nebyl označen jako spam nebo nebyl odstraněn jiným filtrem.\n – Zkontrolujte připojení k internetu.\n – Zkontrolujte, zda jste adresu e-mailu napsali správně.\n – Zkontrolujte, jestli nemáte plnou schránku příchozích správ nebo nedošlo k nějakému jiného problému se schránkou.\n Pokud žádné z uvedených řešení nepomohlo, můžete si e-mail nechat zaslat znovu. Odkaz v prvním e-mailu pak bude deaktivován."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Na adresu %@ byl odeslán přihlašovací e-mail s dalšími pokyny. Dokončete přihlášení podle instrukcí v e-mailu."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Přihlašovací e-mail odeslán"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/da.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/da.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..58bab951 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/da.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Velkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Log ind med mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Angiv din mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Mailadressen er ikke korrekt."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Denne type konto understøttes ikke af denne app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Du har allerede en konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Du har allerede brugt %@. Log ind med %@ for at fortsætte."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Log ind"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Angiv din adgangskode"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Adgangskode skal angives."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Den mail og adgangskode, du angav, stemmer ikke overens."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Mailadressen stemmer ikke overens med en eksisterende konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Mailadressen er for en konto, der er blevet deaktiveret."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Du har indtastet en forkert adgangskode for mange gange. Prøv igen om et par minutter."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Kan ikke finde udbyder til %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Mailadresserne stemmer ikke overens"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Gendan adgangskode"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Få en vejledning sendt til denne mail om, hvordan du nulstiller din adgangskode."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Tjek din mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Følg vejledningen, der blev sendt til %@, for at gendanne din adgangskode."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Opret konto"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "For- og efternavn"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Vælg adgangskode"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Servicevilkår"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privatlivspolitik"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ved at fortsætte indikerer du, at du accepterer vores %@ og %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Mailadressen bruges allerede af en anden konto."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Stærke adgangskoder har mindst 6 tegn og en blanding af bogstaver og tal."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Der kommer for mange kontoanmodninger fra din IP-adresse. Prøv igen om et par minutter."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Du har allerede brugt %@ til at logge ind. Angiv din adgangskode for den pågældende konto."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annuller"; + +/* Back button title. */ +"Back" = "Tilbage"; + +/* Next button title. */ +"Next" = "Næste"; + +/* Save button title. */ +"Save" = "Gem"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Send igen"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Mail"; + +/* Label next to a password text field. */ +"Password" = "Adgangskode"; + +/* Label next to a name text field. */ +"Name" = "Navn"; + +/* Alert title Error. */ +"Error" = "Fejl"; + +/* Alert button title Close. */ +"Close" = "Luk"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sikkerhed"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Tilknyttede konti"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Navn"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Tilføj adgangskode"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Skift adgangskode"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Log ud"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Slet konto"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Har du glemt adgangskoden?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Bekræft, at det er dig"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Skal kontoen slettes?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Dette vil slette alle data, der er knyttet til din konto, og kan ikke fortrydes. Du skal logge ind igen for at fuldføre denne handling"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Dette vil slette alle data, der er knyttet til din konto, og kan ikke fortrydes. Er du sikker på, at du vil slette din konto?"; + +/* Text of Delete action button. */ +"Delete" = "Slet"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Slet konto"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Denne handling kan ikke fortrydes"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Fjern tilknytning"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Tilknyttet konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Fjern tilknytning til konto?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Du kan ikke længere logge ind ved hjælp af din konto"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Fjern tilknytning til konto"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "For at ændre den mailadresse, der er knyttet til din konto, skal du logge ind igen."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "For at ændre din adgangskode skal du først angive din nuværende adgangskode."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Rediger mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Rediger navn"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "For at føje en adgangskode til din konto skal du logge ind igen."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "For at ændre adgangskoden for din konto skal du logge ind igen."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "For at ændre din adgangskode skal du først angive din nuværende adgangskode."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Tilføj adgangskode"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Skift adgangskode"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Log ind med %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Angiv dit navn"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Angiv din mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Angiv din adgangskode"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Ny adgangskode"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Vælg adgangskode"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Har du problemer med at logge ind?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Bekræft mailadresse"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Du er logget ind"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Har du problemer med at modtage mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prøv disse almindelige løsninger: \n - Tjek, om mailen er blevet markeret som spam eller filtreret fra.\n - Tjek din internetforbindelse.\n - Sørg for, at du ikke har stavet din mailadresse forkert.\n - Sørg for, at din indbakke ikke er løbet tør for plads, og at du ikke har andre problemer med indbakken.\n Hvis ovenstående vejledning ikke løste problemet, kan du sende mailen igen. Bemærk, at dette vil deaktivere linket i den gamle mail."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Der er blevet sendt en loginmail med yderligere vejledning til %@. Tjek din mail for at fuldføre loginprocessen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Loginmailen blev sendt"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-AT.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-AT.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..3ad46398 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-AT.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Willkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Mit E-Mail-Adresse anmelden"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "E-Mail-Adresse eingeben"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Diese E-Mail-Adresse ist nicht korrekt."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Diese Art von Konto wird von dieser App nicht unterstützt"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Sie haben bereits ein Konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Sie haben %@ bereits verwendet. Melden Sie sich mit %@ an, um fortzufahren."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Anmelden"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Passwort eingeben"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Passwort darf nicht leer sein."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Die E-Mail-Adresse und das Passwort passen nicht zusammen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Diese E-Mail-Adresse passt zu keinem vorhandenen Konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Diese E-Mail-Adresse gehört zu einem Konto, das deaktiviert wurde."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Sie haben zu oft ein falsches Passwort eingegeben. Versuchen Sie es in einigen Minuten erneut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Anbieter für %@ wurde nicht gefunden."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-Mail-Adressen stimmen nicht überein"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Passwort wiederherstellen"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "In der an diese E-Mail-Adresse gesendeten Anleitung wird beschrieben, wie Sie Ihr Passwort zurücksetzen können."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Im Posteingang nachsehen"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Folgen Sie der an %@ gesendeten Anleitung, um Ihr Passwort zurückzusetzen."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Konto erstellen"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vor- und Nachname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Passwort auswählen"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Nutzungsbedingungen"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Datenschutzerklärung"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Wenn Sie fortfahren, stimmen Sie unseren %@ und unserer %@ zu."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Die E-Mail-Adresse wird bereits von einem anderen Konto verwendet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Starke Passwörter umfassen mindestens sechs Zeichen und eine Mischung aus Buchstaben und Ziffern."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Von Ihrer IP-Adresse werden zu viele Kontoanfragen gesendet. Versuchen Sie es in einigen Minuten erneut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Sie haben bereits %@ zur Anmeldung verwendet. Geben Sie das Passwort für dieses Konto ein."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Abbrechen"; + +/* Back button title. */ +"Back" = "Zurück"; + +/* Next button title. */ +"Next" = "Weiter"; + +/* Save button title. */ +"Save" = "Speichern"; + +/* Send button title. */ +"Send" = "Senden"; + +/* Resend button title. */ +"Resend" = "Erneut senden"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-Mail-Adresse"; + +/* Label next to a password text field. */ +"Password" = "Passwort"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Fehler"; + +/* Alert button title Close. */ +"Close" = "Schließen"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sicherheit"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Verknüpfte Konten"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-Mail-Adresse"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Passwort hinzufügen"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Passwort ändern"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Abmelden"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Konto löschen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Passwort vergessen?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Identität bestätigen"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Konto löschen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Sie müssen sich erneut anmelden, um diese Aktion abzuschließen."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Möchten Sie Ihr Konto wirklich löschen?"; + +/* Text of Delete action button. */ +"Delete" = "Löschen"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Konto löschen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Diese Aktion kann nicht rückgängig gemacht werden"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Verknüpfung aufheben"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Verknüpftes Konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Verknüpfung des Kontos aufheben?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Sie können sich nicht mehr mit Ihrem Konto anmelden"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Verknüpfung des Kontos aufheben"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Wenn Sie die mit Ihrem Konto verknüpfte E-Mail-Adresse ändern möchten, müssen Sie sich erneut anmelden."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-Mail-Adresse bearbeiten"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Name bearbeiten"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Um Ihrem Konto ein Passwort hinzuzufügen, müssen Sie sich erneut anmelden."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Um das Passwort für Ihr Konto zu ändern, müssen Sie sich erneut anmelden."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Passwort hinzufügen"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Passwort ändern"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-Mail-Adresse"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Mit %@ anmelden"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Name eingeben"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "E-Mail-Adresse eingeben"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Passwort eingeben"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Neues Passwort"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Passwort auswählen"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Probleme bei der Anmeldung?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-Mail-Adresse bestätigen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Angemeldet."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Probleme beim Empfangen von E-Mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Versuchen Sie Folgendes: \n – Überprüfen Sie, ob die E-Mail als Spam markiert oder herausgefiltert wurde.\n – Überprüfen Sie Ihre Internetverbindung.\n – Überprüfen Sie die Schreibweise Ihrer E-Mail-Adresse.\n – Überprüfen Sie den Speicherplatz und weitere Einstellungen Ihres Posteingangs, die Probleme bereiten könnten.\n Sollte das Problem nach Ausführung der obigen Schritte weiterhin bestehen, können Sie sich die Anmelde-E-Mail noch einmal zusenden lassen. Hinweis: Der Link in der vorhergehenden E-Mail ist dann nicht mehr gültig."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Wir haben eine Anmelde-E-Mail mit zusätzlichen Informationen an %@ gesendet. Bitte öffnen Sie die E-Mail, um die Anmeldung abzuschließen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Anmelde-E-Mail gesendet"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-CH.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-CH.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..f10c9990 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de-CH.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Willkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Mit E-Mail-Adresse anmelden"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "E-Mail-Adresse eingeben"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Diese E-Mail-Adresse ist nicht korrekt."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Diese Art von Konto wird von dieser App nicht unterstützt"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Sie haben bereits ein Konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Sie haben %@ bereits verwendet. Melden Sie sich mit %@ an, um fortzufahren."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Anmelden"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Passwort eingeben"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Passwort darf nicht leer sein."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Die E-Mail-Adresse und das Passwort passen nicht zusammen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Diese E-Mail-Adresse passt zu keinem vorhandenen Konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Diese E-Mail-Adresse gehört zu einem Konto, das deaktiviert wurde."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Sie haben zu oft ein falsches Passwort eingegeben. Versuchen Sie es in einigen Minuten erneut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Anbieter für %@ wurde nicht gefunden."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-Mail-Adressen stimmen nicht überein"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Passwort wiederherstellen"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "In der an diese E-Mail-Adresse gesendeten Anleitung wird beschrieben, wie Sie Ihr Passwort zurücksetzen können."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Im Posteingang nachsehen"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Folgen Sie der an %@ gesendeten Anleitung, um Ihr Passwort zurückzusetzen."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Konto erstellen"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vor- und Nachname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Passwort auswählen"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Nutzungsbedingungen"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Datenschutzerklärung"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Wenn Sie fortfahren, stimmen Sie unseren %@ und unserer %@ zu."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Die E-Mail-Adresse wird bereits von einem anderen Konto verwendet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Starke Passwörter umfassen mindestens sechs Zeichen und eine Mischung aus Buchstaben und Ziffern."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Von Ihrer IP-Adresse werden zu viele Kontoanfragen gesendet. Versuchen Sie es in einigen Minuten erneut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Sie haben bereits %@ zur Anmeldung verwendet. Geben Sie das Passwort für dieses Konto ein."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Abbrechen"; + +/* Back button title. */ +"Back" = "Zurück"; + +/* Next button title. */ +"Next" = "Weiter"; + +/* Save button title. */ +"Save" = "Speichern"; + +/* Send button title. */ +"Send" = "Senden"; + +/* Resend button title. */ +"Resend" = "Erneut senden"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-Mail-Adresse"; + +/* Label next to a password text field. */ +"Password" = "Passwort"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Fehler"; + +/* Alert button title Close. */ +"Close" = "Schliessen"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sicherheit"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Verknüpfte Konten"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-Mail-Adresse"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Passwort hinzufügen"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Passwort ändern"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Abmelden"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Konto löschen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Passwort vergessen?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Identität bestätigen"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Konto löschen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Sie müssen sich erneut anmelden, um diese Aktion abzuschliessen."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Möchten Sie Ihr Konto wirklich löschen?"; + +/* Text of Delete action button. */ +"Delete" = "Löschen"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Konto löschen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Diese Aktion kann nicht rückgängig gemacht werden"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Verknüpfung aufheben"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Verknüpftes Konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Verknüpfung des Kontos aufheben?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Sie können sich nicht mehr mit Ihrem Konto anmelden"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Verknüpfung des Kontos aufheben"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Wenn Sie die mit Ihrem Konto verknüpfte E-Mail-Adresse ändern möchten, müssen Sie sich erneut anmelden."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-Mail-Adresse bearbeiten"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Name bearbeiten"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Um Ihrem Konto ein Passwort hinzuzufügen, müssen Sie sich erneut anmelden."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Um das Passwort für Ihr Konto zu ändern, müssen Sie sich erneut anmelden."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Passwort hinzufügen"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Passwort ändern"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-Mail-Adresse"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Mit %@ anmelden"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Name eingeben"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "E-Mail-Adresse eingeben"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Passwort eingeben"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Neues Passwort"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Passwort auswählen"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Probleme bei der Anmeldung?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-Mail-Adresse bestätigen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Angemeldet."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Probleme beim Empfangen von E-Mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Versuchen Sie Folgendes: \n – Überprüfen Sie, ob die E-Mail als Spam markiert oder herausgefiltert wurde.\n – Überprüfen Sie Ihre Internetverbindung.\n – Überprüfen Sie die Schreibweise Ihrer E-Mail-Adresse.\n – Überprüfen Sie den Speicherplatz und weitere Einstellungen Ihres Posteingangs, die Probleme bereiten könnten.\n Sollte das Problem nach Ausführung der obigen Schritte weiterhin bestehen, können Sie sich die Anmelde-E-Mail noch einmal zusenden lassen. Hinweis: Der Link in der vorhergehenden E-Mail ist dann nicht mehr gültig."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Wir haben eine Anmelde-E-Mail mit zusätzlichen Informationen an %@ gesendet. Bitte öffnen Sie die E-Mail, um die Anmeldung abzuschliessen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Anmelde-E-Mail gesendet"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..3ad46398 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/de.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Willkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Mit E-Mail-Adresse anmelden"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "E-Mail-Adresse eingeben"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Diese E-Mail-Adresse ist nicht korrekt."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Diese Art von Konto wird von dieser App nicht unterstützt"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Sie haben bereits ein Konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Sie haben %@ bereits verwendet. Melden Sie sich mit %@ an, um fortzufahren."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Anmelden"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Passwort eingeben"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Passwort darf nicht leer sein."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Die E-Mail-Adresse und das Passwort passen nicht zusammen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Diese E-Mail-Adresse passt zu keinem vorhandenen Konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Diese E-Mail-Adresse gehört zu einem Konto, das deaktiviert wurde."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Sie haben zu oft ein falsches Passwort eingegeben. Versuchen Sie es in einigen Minuten erneut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Anbieter für %@ wurde nicht gefunden."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-Mail-Adressen stimmen nicht überein"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Passwort wiederherstellen"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "In der an diese E-Mail-Adresse gesendeten Anleitung wird beschrieben, wie Sie Ihr Passwort zurücksetzen können."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Im Posteingang nachsehen"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Folgen Sie der an %@ gesendeten Anleitung, um Ihr Passwort zurückzusetzen."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Konto erstellen"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vor- und Nachname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Passwort auswählen"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Nutzungsbedingungen"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Datenschutzerklärung"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Wenn Sie fortfahren, stimmen Sie unseren %@ und unserer %@ zu."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Die E-Mail-Adresse wird bereits von einem anderen Konto verwendet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Starke Passwörter umfassen mindestens sechs Zeichen und eine Mischung aus Buchstaben und Ziffern."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Von Ihrer IP-Adresse werden zu viele Kontoanfragen gesendet. Versuchen Sie es in einigen Minuten erneut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Sie haben bereits %@ zur Anmeldung verwendet. Geben Sie das Passwort für dieses Konto ein."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Abbrechen"; + +/* Back button title. */ +"Back" = "Zurück"; + +/* Next button title. */ +"Next" = "Weiter"; + +/* Save button title. */ +"Save" = "Speichern"; + +/* Send button title. */ +"Send" = "Senden"; + +/* Resend button title. */ +"Resend" = "Erneut senden"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-Mail-Adresse"; + +/* Label next to a password text field. */ +"Password" = "Passwort"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Fehler"; + +/* Alert button title Close. */ +"Close" = "Schließen"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sicherheit"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Verknüpfte Konten"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-Mail-Adresse"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Passwort hinzufügen"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Passwort ändern"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Abmelden"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Konto löschen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Passwort vergessen?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Identität bestätigen"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Konto löschen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Sie müssen sich erneut anmelden, um diese Aktion abzuschließen."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Möchten Sie Ihr Konto wirklich löschen?"; + +/* Text of Delete action button. */ +"Delete" = "Löschen"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Konto löschen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Diese Aktion kann nicht rückgängig gemacht werden"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Verknüpfung aufheben"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Verknüpftes Konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Verknüpfung des Kontos aufheben?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Sie können sich nicht mehr mit Ihrem Konto anmelden"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Verknüpfung des Kontos aufheben"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Wenn Sie die mit Ihrem Konto verknüpfte E-Mail-Adresse ändern möchten, müssen Sie sich erneut anmelden."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-Mail-Adresse bearbeiten"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Name bearbeiten"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Um Ihrem Konto ein Passwort hinzuzufügen, müssen Sie sich erneut anmelden."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Um das Passwort für Ihr Konto zu ändern, müssen Sie sich erneut anmelden."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Passwort hinzufügen"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Passwort ändern"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-Mail-Adresse"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Mit %@ anmelden"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Name eingeben"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "E-Mail-Adresse eingeben"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Passwort eingeben"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Neues Passwort"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Passwort auswählen"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Probleme bei der Anmeldung?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-Mail-Adresse bestätigen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Angemeldet."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Probleme beim Empfangen von E-Mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Versuchen Sie Folgendes: \n – Überprüfen Sie, ob die E-Mail als Spam markiert oder herausgefiltert wurde.\n – Überprüfen Sie Ihre Internetverbindung.\n – Überprüfen Sie die Schreibweise Ihrer E-Mail-Adresse.\n – Überprüfen Sie den Speicherplatz und weitere Einstellungen Ihres Posteingangs, die Probleme bereiten könnten.\n Sollte das Problem nach Ausführung der obigen Schritte weiterhin bestehen, können Sie sich die Anmelde-E-Mail noch einmal zusenden lassen. Hinweis: Der Link in der vorhergehenden E-Mail ist dann nicht mehr gültig."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Wir haben eine Anmelde-E-Mail mit zusätzlichen Informationen an %@ gesendet. Bitte öffnen Sie die E-Mail, um die Anmeldung abzuschließen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Anmelde-E-Mail gesendet"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/el.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/el.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..7cee33c2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/el.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Καλώς ήρθατε"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Σύνδεση μέσω ηλεκτρονικού ταχυδρομείου"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Εισαγάγετε τη διεύθυνση ηλεκτρονικού ταχυδρομείου σας"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Αυτή η διεύθυνση ηλεκτρονικού ταχυδρομείου δεν είναι σωστή."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Αυτός ο τύπος λογαριασμού δεν υποστηρίζεται από αυτήν την εφαρμογή"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Έχετε ήδη λογαριασμό"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Έχετε ήδη χρησιμοποιήσει το %@. Συνδεθείτε με %@ για να συνεχίσετε."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Σύνδεση"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Εισαγάγετε τον κωδικό πρόσβασής σας"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Ο κωδικός πρόσβασης δεν μπορεί να είναι κενός."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Η διεύθυνση ηλεκτρονικού ταχυδρομείου και ο κωδικός πρόσβασης δεν ταιριάζουν."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Αυτή η διεύθυνση ηλεκτρονικού ταχυδρομείου δεν ταιριάζει με κάποιον υπάρχοντα λογαριασμό."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Αυτή η διεύθυνση ηλεκτρονικού ταχυδρομείου αφορά έναν λογαριασμό που έχει απενεργοποιηθεί."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Πληκτρολογήσατε πολλές φορές λανθασμένο κωδικό πρόσβασης. Δοκιμάστε ξανά σε λίγα λεπτά."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Δεν είναι δυνατή η εύρεση του παρόχου για %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Οι διευθύνσεις ηλεκτρονικού ταχυδρομείου δεν ταιριάζουν"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Ανάκτηση κωδικού πρόσβασης"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Δείτε τις οδηγίες που στάλθηκαν σε αυτήν τη διεύθυνση ηλεκτρονικού ταχυδρομείου, οι οποίες εξηγούν πώς να επαναφέρετε τον κωδικό πρόσβασής σας."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Ελέγξτε τα εισερχόμενα του ηλεκτρονικού ταχυδρομείου σας"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Ακολουθήστε τις οδηγίες που στάλθηκαν στο %@ για να ανακτήσετε τον κωδικό πρόσβασής σας."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Δημιουργία λογαριασμού"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Όνομα και επώνυμο"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Επιλέξτε κωδικό πρόσβασης"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Όρους Παροχής Υπηρεσιών"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Πολιτική απορρήτου"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Αν συνεχίσετε, δηλώνετε ότι αποδέχεστε τους %@ και την %@ μας."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Αυτή η διεύθυνση ηλεκτρονικού ταχυδρομείου χρησιμοποιείται ήδη από άλλον λογαριασμό."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Οι ισχυροί κωδικοί πρόσβασης έχουν τουλάχιστον 6 χαρακτήρες και έναν συνδυασμό γραμμάτων και αριθμών."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Η διεύθυνση IP έχει στείλει πάρα πολλά αιτήματα λογαριασμού. Δοκιμάστε ξανά σε λίγα λεπτά."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Χρησιμοποιήσατε ήδη το %@ για να συνδεθείτε. Εισαγάγετε τον κωδικό πρόσβασης για αυτόν τον λογαριασμό."; + +/* OK button title. */ +"OK" = "ΟΚ"; + +/* Cancel button title. */ +"Cancel" = "Ακύρωση"; + +/* Back button title. */ +"Back" = "Πίσω"; + +/* Next button title. */ +"Next" = "Επόμενο"; + +/* Save button title. */ +"Save" = "Αποθήκευση"; + +/* Send button title. */ +"Send" = "Αποστολή"; + +/* Resend button title. */ +"Resend" = "Επανάληψη αποστολής"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Ηλεκτρονικό ταχυδρομείο"; + +/* Label next to a password text field. */ +"Password" = "Κωδικός πρόσβασης"; + +/* Label next to a name text field. */ +"Name" = "Όνομα"; + +/* Alert title Error. */ +"Error" = "Σφάλμα"; + +/* Alert button title Close. */ +"Close" = "Κλείσιμο"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Προφίλ"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Ασφάλεια"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Συνδεδεμένοι λογαριασμοί"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Όνομα"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Ηλεκτρονικό ταχυδρομείο"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Προσθήκη κωδικού πρόσβασης"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Αλλαγή κωδικού πρόσβασης"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Έξοδος"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Διαγραφή λογαριασμού"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Ξεχάσατε τον κωδικό πρόσβασής σας;"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Επαληθεύστε ότι είστε εσείς"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Διαγραφή λογαριασμού;"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Αυτή η ενέργεια θα διαγράψει όλα τα δεδομένα που συσχετίζονται με τον λογαριασμό σας και δεν είναι δυνατή η αναίρεσή της. Για να ολοκληρώσετε αυτήν την ενέργεια, θα πρέπει να συνδεθείτε ξανά"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Αυτή η ενέργεια θα διαγράψει όλα τα δεδομένα που συσχετίζονται με τον λογαριασμό σας και δεν είναι δυνατή η αναίρεσή της. Είστε σίγουροι ότι θέλετε να διαγράψετε τον λογαριασμό σας;"; + +/* Text of Delete action button. */ +"Delete" = "Διαγραφή"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Διαγραφή λογαριασμού"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Δεν είναι δυνατή η αναίρεση αυτής της ενέργειας"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Αποσύνδεση"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Συνδεδεμένος λογαριασμός"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Αποσύνδεση λογαριασμού;"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Δεν θα μπορείτε πλέον να συνδεθείτε χρησιμοποιώντας τον λογαριασμό σας"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Αποσύνδεση λογαριασμού"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Για να αλλάξετε τη διεύθυνση που συσχετίζεται με τον λογαριασμό σας, θα πρέπει να συνδεθείτε ξανά."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Για να αλλάξετε τον κωδικό πρόσβασής σας, θα πρέπει πρώτα να εισαγάγετε τον τρέχοντα κωδικό πρόσβασης."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Επεξεργασία διεύθυνσης ηλεκτρονικού ταχυδρομείου"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Επεξεργασία ονόματος"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Για να προσθέσετε κωδικό πρόσβασης στον λογαριασμό σας, θα πρέπει να συνδεθείτε ξανά."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Για να αλλάξετε κωδικό πρόσβασης στον λογαριασμό σας, θα πρέπει να συνδεθείτε ξανά."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Για να αλλάξετε τον κωδικό πρόσβασής σας, θα πρέπει πρώτα να εισαγάγετε τον τρέχοντα κωδικό πρόσβασης."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Προσθήκη κωδικού πρόσβασης"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Αλλαγή κωδικού πρόσβασης"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Ηλεκτρονικό ταχυδρομείο"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Σύνδεση μέσω %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Εισαγάγετε το όνομά σας"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Εισαγάγετε τη διεύθυνση ηλεκτρονικού ταχυδρομείου σας"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Εισαγάγετε τον κωδικό πρόσβασής σας"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Νέος κωδικός πρόσβασης"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Επιλέξτε κωδικό πρόσβασης"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Πρόβλημα σύνδεσης;"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Επιβεβαίωση διεύθυνσης ηλεκτρονικού ταχυδρομείου"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Συνδέθηκε!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Αντιμετωπίζετε πρόβλημα με τη λήψη των μηνυμάτων ηλεκτρονικού ταχυδρομείου;"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Δοκιμάστε αυτές τις συνήθεις λύσεις: \n - Ελέγξτε αν το μήνυμα ηλεκτρονικού ταχυδρομείου επισημάνθηκε ως ανεπιθύμητο ή έχει φιλτραριστεί.\n - Ελέγξτε τη σύνδεσή σας στο διαδίκτυο.\n - Βεβαιωθείτε ότι δεν έχετε γράψει λάθος τη διεύθυνση ηλεκτρονικού ταχυδρομείου.\n - Βεβαιωθείτε ότι δεν έχει γεμίσει ο χώρος εισερχομένων ή ότι δεν υπάρχουν άλλα προβλήματα που σχετίζονται με τις ρυθμίσεις εισερχομένων.\n Αν τα παραπάνω βήματα δεν λειτούργησαν, μπορείτε να στείλετε ξανά το μήνυμα ηλεκτρονικού ταχυδρομείου. Έχετε υπόψη ότι με αυτήν την ενέργεια, ο σύνδεσμος στο παλιότερο μήνυμα ηλεκτρονικού ταχυδρομείου θα απενεργοποιηθεί."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Ένα μήνυμα ηλεκτρονικού ταχυδρομείου σύνδεσης με πρόσθετες οδηγίες στάλθηκε στη διεύθυνση %@. Ελέγξτε τη διεύθυνση ηλεκτρονικού ταχυδρομείου για να ολοκληρώσετε τη σύνδεση."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Το μήνυμα ηλεκτρονικού ταχυδρομείου σύνδεσης στάλθηκε"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-AU.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-AU.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-AU.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-CA.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-CA.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-CA.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-GB.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-GB.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-GB.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IE.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IE.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IE.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IN.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IN.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-IN.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-SG.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-SG.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-SG.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-ZA.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-ZA.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d1c7a39c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en-ZA.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Incorrect email address."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You've already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password that you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn't match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You've entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Receive instructions to this email that explain how to reset your password"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First name & surname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You've already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgotten password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify that it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone. You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure that you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add a password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change your account's password, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n – Check whether the email was marked as spam or filtered.\n – Check your internet connection.\n – Check that you did not misspell your email.\n – Check that your inbox space is not running out, or for other inbox settings-related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..fa9ddce3 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/en.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Sign in with email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Enter your email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "That email address isn't correct."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "This type of account isn't supported by this app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "You already have an account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "You’ve already used %@. Sign in with %@ to continue."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Enter your password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Password cannot be empty."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "The email and password you entered don't match."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "That email address doesn’t match an existing account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "That email address is for an account that has been disabled."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "You’ve entered an incorrect password too many times. Try again in a few minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Can't find provider for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Emails don't match"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recover password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Get instructions sent to this email that explain how to reset your password."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Check your email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Follow the instructions sent to %@ to recover your password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Create account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "First & last name"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choose password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Terms of Service"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacy Policy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "By continuing, you are indicating that you accept our %@ and %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "The email address is already in use by another account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Strong passwords have at least 6 characters and a mix of letters and numbers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Too many account requests are coming from your IP address. Try again in a few minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "You’ve already used %@ to sign in. Enter your password for that account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancel"; + +/* Back button title. */ +"Back" = "Back"; + +/* Next button title. */ +"Next" = "Next"; + +/* Save button title. */ +"Save" = "Save"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Resend"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Close"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Security"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linked Accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Add password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Change password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Delete Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Forgot password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verify it's you"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Delete Account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "This will erase all data associated with your account, and can't be undone You will need to sign in again to complete this action"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "This will erase all data associated with your account, and can't be undone. Are you sure you want to delete your account?"; + +/* Text of Delete action button. */ +"Delete" = "Delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Delete account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "This action can't be undone"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linked account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Unlink account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "You will no longer be able to sign in using your account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Unlink account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "To change email address associated with your account, you will need to sign in again."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit name"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "To add password to your account, you will need to sign in again."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "To change password to your account, you will need to sign in again."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "In order to change your password, you first need to enter your current password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Add password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Change password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Sign in with %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Enter your name"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Enter your email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Enter your password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "New password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choose password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Trouble signing in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirm Email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Signed in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Trouble getting emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Try these common fixes: \n - Check if the email was marked as spam or filtered.\n - Check your internet connection.\n - Check that you did not misspell your email.\n - Check that your inbox space is not running out or other inbox settings related issues.\n If the steps above didn't work, you can resend the email. Note that this will deactivate the link in the older email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A sign-in email with additional instructions was sent to %@. Check your email to complete sign-in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Sign-in email Sent"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-419.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-419.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-419.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-AR.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-AR.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-AR.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-BO.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-BO.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-BO.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CL.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CL.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CL.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CO.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CO.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CO.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CR.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CR.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-CR.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-DO.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-DO.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-DO.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-EC.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-EC.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-EC.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-GT.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-GT.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-GT.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-HN.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-HN.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-HN.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-MX.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-MX.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-MX.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-NI.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-NI.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-NI.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PA.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PA.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PA.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PE.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PE.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PE.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PR.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PR.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PR.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PY.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PY.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-PY.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-SV.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-SV.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-SV.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-US.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-US.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-US.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-UY.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-UY.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-UY.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-VE.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-VE.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..29b57287 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es-VE.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Acceder con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ingresa tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "La dirección de correo electrónico es incorrecta."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "El tipo de cuenta no es compatible con esta app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya usaste %@. Accede con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Acceder"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ingresa la contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "El campo de contraseña no puede estar vacío."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "El correo electrónico y la contraseña que ingresaste no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con una cuenta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico corresponde a una cuenta que se inhabilitó."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ingresaste una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se encuentra ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones para cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Revisa tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que se enviaron a %@ para restablecer la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elegir contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Condiciones del servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, indicas que aceptas nuestras %@ y %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras deben tener al menos 6 caracteres, además de incluir letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Recibimos demasiadas solicitudes de cuenta desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya usaste %@ para acceder. Ingresa la contraseña correspondiente."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Agregar contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Salir"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Borrar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Olvidaste la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica tu identidad"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Quieres borrar la cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. Debes acceder de nuevo para realizarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados con tu cuenta y no se puede deshacer. ¿Estás seguro de que quieres borrar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Borrar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Borrar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Quieres desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás acceder con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo electrónico asociada con tu cuenta, debes acceder de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para agregar una contraseña a tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes acceder de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para cambiar tu contraseña, primero debes ingresar la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Agregar contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Acceder con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ingresa tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ingresa tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ingresa la contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elegir contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿Tienes problemas para acceder?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accediste"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿Tienes problemas para recibir correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba estas soluciones comunes: \n- Verifica si el correo electrónico se marcó como spam o se filtró.\n- Comprueba tu conexión a Internet.\n- Verifica que escribiste bien tu correo electrónico.\n- Verifica que tu bandeja de entrada no esté llena o revisa cualquier otro problema relacionado con la configuración de la bandeja de entrada.\nSi los pasos anteriores no funcionaron, reenvía el correo electrónico. Ten en cuenta que esta acción desactivará el vínculo en el correo electrónico anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se envió un correo electrónico de acceso con instrucciones adicionales a %@. Revisa tu bandeja de entrada para completar el proceso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Se envió el correo electrónico de acceso"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..848ae18a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/es.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Te damos la bienvenida"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Iniciar sesión con el correo electrónico"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Introduce tu correo electrónico"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "El correo electrónico no es correcto."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Esta aplicación no admite este tipo de cuenta"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Ya tienes una cuenta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ya has usado %@. Inicia sesión con %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Iniciar sesión"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Introduce tu contraseña"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "La contraseña no puede estar vacía."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "La dirección de correo electrónico y contraseña que has introducido no coinciden."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "La dirección de correo electrónico no coincide con ninguna cuenta."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "La dirección de correo electrónico pertenece a una cuenta que se ha inhabilitado."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Has introducido una contraseña incorrecta demasiadas veces. Vuelve a intentarlo en unos minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "No se ha encontrado a ningún proveedor de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Los correos electrónicos no coinciden"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar contraseña"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Recibe un correo electrónico con instrucciones sobre cómo cambiar la contraseña."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Consulta tu correo electrónico"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sigue las instrucciones que hemos enviado a %@ para recuperar la contraseña."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crear cuenta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nombre y apellidos"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Elige una contraseña"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "condiciones de servicio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de privacidad"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Si continúas, confirmas que aceptas nuestras %@ y nuestra %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Otra cuenta ya usa esta dirección de correo electrónico."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Las contraseñas seguras contienen 6 caracteres como mínimo y combinan letras y números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Estamos recibiendo demasiadas solicitudes desde tu dirección IP. Vuelve a intentarlo en unos minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ya has usado %@ para iniciar sesión. Introduce la contraseña de esa cuenta."; + +/* OK button title. */ +"OK" = "Aceptar"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Atrás"; + +/* Next button title. */ +"Next" = "Siguiente"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Correo electrónico"; + +/* Label next to a password text field. */ +"Password" = "Contraseña"; + +/* Label next to a name text field. */ +"Name" = "Nombre"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Cerrar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Cuentas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nombre"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Correo electrónico"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Añadir contraseña"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambiar contraseña"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Cerrar sesión"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Eliminar cuenta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "¿Has olvidado la contraseña?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica que eres tú"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "¿Eliminar cuenta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta acción borrará todos los datos asociados a la cuenta y no se puede deshacer. Tendrás que volver a iniciar sesión para completarla"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta acción borrará todos los datos asociados a la cuenta y no se puede deshacer. ¿Seguro que quieres eliminar tu cuenta?"; + +/* Text of Delete action button. */ +"Delete" = "Eliminar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Eliminar cuenta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Esta acción no se puede deshacer"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cuenta vinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "¿Desvincular la cuenta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ya no podrás iniciar sesión con tu cuenta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular la cuenta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para cambiar la dirección de correo asociada a la cuenta, debes iniciar sesión de nuevo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para poder cambiar la contraseña, primero debes introducir la contraseña actual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar correo electrónico"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nombre"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para añadir una contraseña a tu cuenta, debes iniciar sesión de nuevo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para cambiar la contraseña de tu cuenta, debes iniciar sesión de nuevo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para poder cambiar la contraseña, primero debes introducir la contraseña actual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Añadir contraseña"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambiar contraseña"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Correo electrónico"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Iniciar sesión con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Introduce tu nombre"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Introduce tu correo electrónico"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Introduce tu contraseña"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nueva contraseña"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Elige una contraseña"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "¿No puedes iniciar sesión?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmar la dirección de correo electrónico"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Has iniciado sesión."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "¿No puedes recibir los correos electrónicos?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prueba las soluciones más habituales: \n. Asegúrate de que el correo electrónico no se ha filtrado ni marcado como spam.\n. Comprueba tu conexión a Internet.\n. Asegúrate de que has escrito bien tu dirección de correo electrónico.\n. Comprueba que no te estés quedando sin espacio en la bandeja de entrada y que no haya ningún problema con su configuración.\n. Si no se ha resuelto el problema con los pasos mencionados, puedes volver a enviar el correo electrónico. Si lo haces, se desactivará el enlace del mensaje de correo anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Se ha enviado un correo electrónico de inicio de sesión con más instrucciones a %@. Consulta tu bandeja de entrada para completar el inicio de sesión."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Correo electrónico de inicio de sesión enviado"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fa.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fa.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..e4132c86 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fa.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "خوش‌ آمدید"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ورود به سیستم با ایمیل "; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "رایانامه‌تان را وارد کنید"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "این نشانی ایمیل درست نیست."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "این برنامه از این نوع حساب‌ پشتیبانی نمی‌کند"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "از قبل حسابی دارید"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "قبلاً از %@ استفاده کرده‌اید. برای ادامه با %@ وارد سیستم شوید."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "ورود به سیستم"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "گذرواژه‌تان را وارد کنید"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "فیلد گذرواژه نمی‌تواند خالی باشد."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "ایمیل و گذرواژه وارد‌شده با هم مطابقت ندارند."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "این نشانی ایمیل با هیچ حسابی مطابقت ندارد."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "این نشانی ایمیل متعلق به حسابی است که غیرفعال شده است."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "دفعات زیادی گذرواژه اشتباه وارد کرده‌اید. پس از چند دقیقه دوباره امتحان کنید."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "قادر به پیدا کردن ارائه‌دهنده %@ نیست."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ایمیل‌ها با هم مطابقت ندارند"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "بازیابی گذرواژه"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "دستورالعمل نحوه بازنشانی گذرواژه‌تان به این ایمیل ارسال شده است، آن را ببینید."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "رایانامه‌تان را بررسی کنید"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "برای بازیابی گذرواژه‌تان، دستورالعمل‌های ارسال‌شده به %@ را دنبال کنید."; + +/* Title for sign up screen. */ +"SignUpTitle" = "ایجاد حساب"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "نام و نام خانوادگی"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "یک گذرواژه انتخاب کنید"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "شرایط خدمات"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "خط‌مشی رازداری"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "درصورت ادامه‌ دادن، موافقتتان را با %@ و %@ ما اعلام می‌کنید."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "قبلاً از این نشانی ایمیل برای حساب دیگری استفاده شده است."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "گذرواژه قوی باید حداقل شامل ۶ نویسه‌ و ترکیبی از حروف و اعداد باشد."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "تعداد زیادی درخواست حساب از نشانی IP شما درحال ارسال است. پس از چند دقیقه دوباره امتحان کنید."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "قبلاً از %@ برای ورود به سیستم استفاده کرده‌اید. گذرواژه این حساب را وارد کنید."; + +/* OK button title. */ +"OK" = "تأیید"; + +/* Cancel button title. */ +"Cancel" = "لغو"; + +/* Back button title. */ +"Back" = "قبلی"; + +/* Next button title. */ +"Next" = "بعدی"; + +/* Save button title. */ +"Save" = "ذخیره"; + +/* Send button title. */ +"Send" = "ارسال"; + +/* Resend button title. */ +"Resend" = "ارسال مجدد"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ایمیل "; + +/* Label next to a password text field. */ +"Password" = "گذرواژه"; + +/* Label next to a name text field. */ +"Name" = "نام"; + +/* Alert title Error. */ +"Error" = "خطا"; + +/* Alert button title Close. */ +"Close" = "بستن"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "نمایه"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "امنیت"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "حساب‌های مرتبط"; + +/* Account Settings cell title Name. */ +"AS_Name" = "نام"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ایمیل "; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "افزودن گذرواژه"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "تغییر گذرواژه"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "خروج از سیستم"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "حذف حساب"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "گذرواژه‌تان را فراموش کرده‌اید؟"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "تأیید کنید این خود شما هستید"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "حساب حذف شود؟"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "با این کار همه داده‌های مرتبط با حسابتان پاک می‌شود که قابل واگرد نیست. برای تکمیل این اقدام باید دوباره وارد سیستم شوید"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "با این کار همه داده‌های مرتبط با حسابتان پاک می‌شود که قابل واگرد نیست. مطمئنید می‌خواهید حسابتان حذف شود؟"; + +/* Text of Delete action button. */ +"Delete" = "حذف"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "حذف حساب"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "این کار واگردشدنی نیست."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "لغو پیوند"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "حساب پیوندی"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "پیوند حساب لغو شود؟"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "دیگر نمی‌توانید با استفاده از این حساب وارد سیستم شوید"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "لغو پیوند حساب"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "برای تغییر نشانی ایمیل مرتبط با حسابتان باید دوباره وارد سیستم شوید."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "برای تغییر گذرواژه‌‌، ابتدا باید گذرواژه کنونی‌تان را وارد کنید."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ویرایش ایمیل "; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "ویرایش نام"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "برای افزودن گذرواژه به حسابتان باید دوباره وارد سیستم شوید."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "برای تغییر گذرواژه حسابتان باید دوباره وارد سیستم شوید."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "برای تغییر گذرواژه‌‌، ابتدا باید گذرواژه کنونی‌تان را وارد کنید."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "افزودن گذرواژه"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "تغییر گذرواژه"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ایمیل "; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google‏"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "ورود به سیستم با %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "نام خود را وارد کنید"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "رایانامه‌تان را وارد کنید"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "گذرواژه‌تان را وارد کنید"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "گذرواژه جدید"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "گذرواژه انتخاب کنید"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "مشکلی در ورود به سیستم دارید؟"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "تأیید ایمیل"; + +/* Title of successfully signed in label. */ +"SignedIn" = "به سیستم وارد شدید!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "در دریافت ایمیل مشکل دارید؟"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "این رفع اشکال‌های رایج را امتحان کنید: \n - ببینید ایمیل به‌عنوان هرزنامه یا فیلترشده مشخص نشده باشد.\n - اتصال اینترنتتان را بررسی کنید.\n - مطمئن شوید املای ایمیلتان را درست وارد کرده باشید.\n - مطمئن شوید فضای صندوق ورودی‌تان روبه‌اتمام نباشد یا مشکل دیگری در تنظیمات صندوق ورودی وجود نداشته باشد.\n اگر اقدامات بالا به رفع مشکل کمک نکرد، می‌توانید ایمیل را مجدداً ارسال کنید. توجه کنید که با این کار، پیوند موجود در ایمیل قبلی غیرفعال می‌شود."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "ایمیل ورود به سیستم، حاوی دستورالعمل‌های بیشتر، به %@ ارسال شد. برای تکمیل ورود به سیستم، ایمیلتان را بررسی کنید."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "ایمیل ورود به سیستم ارسال شد"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fi.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fi.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..6349b4db --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fi.lproj/FirebaseAuthUI.strings @@ -0,0 +1,270 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Tervetuloa"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Kirjaudu sähköpostilla"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Anna sähköpostiosoitteesi"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Virheellinen sähköpostiosoite"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Sovellus ei tue tätä tilityyppiä."; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Sinulla on jo tili."; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Olet jo käyttänyt osoitetta %@. Jatka kirjautumalla palvelun %@ kautta."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Kirjaudu sisään"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Anna salasana"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Salasana ei voi olla tyhjä."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Antamasi sähköpostiosoite ja salasana eivät täsmää."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Sähköpostiosoite ei vastaa aiemmin luotua tiliä."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Sähköpostiosoite on rekisteröity tiliin, joka on poistettu käytöstä."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Olet antanut virheellisen salasanan liian monta kertaa. Yritä uudelleen muutaman minuutin kuluttua."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Palveluntarjoajaa ei löydy osoitteelle %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Sähköpostit eivät täsmää."; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Palauta salasana"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Tilaa tähän sähköpostiin ohjeet, joissa neuvotaan, miten voit nollata salasanan."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Tarkista sähköpostisi"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Palauta salasana noudattamalla osoitteeseen %@ lähetettyjä ohjeita."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Luo tili"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Etu- ja sukunimi"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Valitse salasana"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Käyttöehdot"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Tietosuojakäytäntö"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Jatkamalla vahvistat hyväksyväsi seuraavat: %@ ja %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Tämä sähköpostiosoite on jo rekisteröity toiseen tiliin."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Vahvassa salasanassa on vähintään 6 merkkiä, ja se sisältää kirjaimia ja numeroita."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "IP-osoitteestasi on lähetetty liian monta tilipyyntöä. Yritä uudelleen muutaman minuutin kuluttua."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Olet jo käyttänyt osoitetta %@ + kirjautumiseen. Anna kyseisen tilin salasana."; + +/* OK button title. */ +"OK" = "Ok"; + +/* Cancel button title. */ +"Cancel" = "Peruuta"; + +/* Back button title. */ +"Back" = "Takaisin"; + +/* Next button title. */ +"Next" = "Seuraava"; + +/* Save button title. */ +"Save" = "Tallenna"; + +/* Send button title. */ +"Send" = "Lähetä"; + +/* Resend button title. */ +"Resend" = "Lähetä uudelleen"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Sähköposti"; + +/* Label next to a password text field. */ +"Password" = "Salasana"; + +/* Label next to a name text field. */ +"Name" = "Nimi"; + +/* Alert title Error. */ +"Error" = "Virhe"; + +/* Alert button title Close. */ +"Close" = "Sulje"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profiili"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Turvallisuus"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Linkitetyt tilit"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nimi"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Sähköposti"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Lisää salasana"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Vaihda salasana"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Kirjaudu ulos"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Poista tili"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Unohditko salasanasi?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Vahvista henkilöllisyytesi"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Poistetaanko tili?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Tämä poistaa kaikki tiliisi liittyvät tiedot, eikä toimintoa voi kumota. Sinun pitää kirjautua sisään uudelleen, jotta voit suorittaa toiminnon loppuun."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Tämä poistaa kaikki tiliisi liittyvät tiedot, eikä toimintoa voi kumota. Haluatko varmasti poistaa tilisi?"; + +/* Text of Delete action button. */ +"Delete" = "Poista"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Poista tili"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tätä toimintoa ei voi kumota."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Poista linkitys"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Linkitetty tili"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Poistetaanko tilin linkitys?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Et enää voi kirjautua sisään tililläsi."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Poista tilin linkitys"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Jotta voit vaihtaa tiliisi liittyvän sähköpostin, sinun pitää kirjautua sisään uudelleen."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Jotta voit vaihtaa salasanasi, sinun on annettava ensin nykyinen salasanasi."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Muokkaa sähköpostia"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Muokkaa nimeä"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Jotta voit lisätä salasanan tiliisi, sinun pitää kirjautua sisään uudelleen."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Jotta voit vaihtaa tilisi salasanan, sinun pitää kirjautua sisään uudelleen."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Jotta voit vaihtaa salasanasi, sinun on annettava ensin nykyinen salasanasi."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Lisää salasana"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Vaihda salasana"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Sähköposti"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Kirjaudu palvelun %@ kautta"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Anna nimesi"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Anna sähköpostiosoitteesi"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Anna salasana"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Uusi salasana"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Valitse salasana"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Eikö kirjautuminen onnistu?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Vahvista sähköposti"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Kirjauduttu"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Ongelmia sähköpostiviestien saamisessa?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Kokeile näitä yleisiä ratkaisuja: \n – Tarkista, merkittiinkö viesti roskapostiksi tai suodatettiinko se.\n – Tarkista internetyhteytesi.\n – Tarkista, että kirjoitit sähköpostiosoitteesi oikein.\n – Tarkista, ettei postilaatikkosi tila ole loppumassa tai ettei postilaatikon asetuksissa ole muita ongelmia.\n – Jos edellä olevista ratkaisuista ei ollut apua, voit lähettää viestin uudelleen. Huomaa, että tällöin aiemmassa viestissä oleva linkki poistetaan käytöstä."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Lisäohjeita sisältävä kirjautumisviesti lähetettiin osoitteeseen %@. Tarkista sähköpostisi kirjautumisen suorittamiseksi loppuun."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Kirjautumisviesti lähetetty"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fil.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fil.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..dde53552 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fil.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welcome"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Mag-sign in gamit ang email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ilagay ang iyong email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Mali ang email address na iyon."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Hindi sinusuportahan sa app na ito ang ganitong uri ng account"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Mayroon ka nang account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Nagamit mo na ang %@. Mag-sign in gamit ang %@ upang magpatuloy."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Mag-sign in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ilagay ang iyong password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Hindi maaaring walang laman ang password."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Hindi nagtutugma ang inilagay mong email at password."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Hindi tumutugma ang email address na iyon sa isang kasalukuyang account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Ang email address na iyon ay para sa isang na-disable nang account."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Nagpasok ka ng di-wastong password nang masyadong maraming beses. Pakisubukang muli pagkalipas ng ilang minuto."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Hindi makahanap ng provider para sa %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Hindi tumutugma ang mga email"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "I-recover ang password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Kumuha ng mga tagubilin na ipadala sa email na ito na magpapaliwanag kung paano i-reset ang iyong password."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Suriin ang iyong email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Sundin ang mga tagubilin na ipinadala sa %@ upang ma-recover ang iyong password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Gumawa ng account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Pangalan at apelyido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Pumili ng password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Mga Tuntunin ng Serbisyo"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Patakaran sa Privacy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Sa pagpapatuloy, ipinababatid mo na tinatanggap mo ang aming %@ at %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ginagamit na ang email address ng ibang account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Kailangang may 6 na character man lang at kumbinasyon ng mga titik at mga numero ang mga malalakas na password."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Masyadong maraming kahilingan ng account mula sa iyong IP address. Subukang muli pagkalipas ng ilang minuto."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Nagamit mo na ang %@ upang mag-sign in. Ilagay ang iyong password para sa account na iyon."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Kanselahin"; + +/* Back button title. */ +"Back" = "Bumalik"; + +/* Next button title. */ +"Next" = "Susunod"; + +/* Save button title. */ +"Save" = "I-save"; + +/* Send button title. */ +"Send" = "Ipadala"; + +/* Resend button title. */ +"Resend" = "Muling Ipadala"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Pangalan"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Isara"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profile"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Seguridad"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Mga Naka-link na Account"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Pangalan"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Mag-email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Magdagdag ng password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Palitan ang password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Mag-sign Out"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Tanggalin ang Account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Nakalimutan ang password?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "I-verify na ikaw ito"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "I-delete ang Account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Buburahin nito ang lahat ng data na nauugnay sa iyong account, at hindi na maa-undo Kailangan mong mag-sign in muli upang kumpletuhin ang pagkilos na ito"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Buburahin nito ang lahat ng data na nauugnay sa iyong account, at hindi na maa-undo. Sigurado ka bang gusto mong i-delete ang iyong account?"; + +/* Text of Delete action button. */ +"Delete" = "I-delete"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "I-delete ang account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Hindi na maa-undo ang pagkilos na ito"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "I-unlink"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Naka-link na account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "I-unlink ang account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Hindi ka na makakapag-sign in gamit ang iyong account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "I-unlink ang account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Upang mabago ang email address na kaugnay ng iyong account, kakailanganin mong mag-sign in muli."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Upang baguhin ang iyong password, kailangan mo munang ipasok ang iyong kasalukuyang password."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "I-edit ang email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "I-edit ang pangalan"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Upang magdagdag ng password sa iyong account, kailangan mong mag-sign in muli."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Upang baguhin ang password sa iyong account, kailangan mong mag-sign in muli."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Upang baguhin ang iyong password, kailangan mo munang ipasok ang iyong kasalukuyang password."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Magdagdag ng password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Palitan ang password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Mag-email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Fecebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Mag-sign in gamit ang %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ilagay ang iyong pangalan"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ilagay ang iyong email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ilagay ang iyong password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Bagong password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Pumili ng password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Nagkaproblema sa pag-sign in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Kumpirmahin ang Email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Naka-sign in!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Nagkakaproblema sa pagtanggap ng mga email?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Subukan ang mga karaniwang pag-aayos na ito: \n - Tingnan kung minarkahan ang email bilang spam o na-filter.\n - Tingnan ang iyong koneksyon sa internet.\n - Tiyakin na hindi ka nagkamali sa pagbaybay ng iyong email.\n - Tingnan kung hindi pa nauubusan ng espasyo ang iyong inbox o may iba pang isyu na may kinalaman sa mga setting ng inbox.\n Kung hindi umubra ang mga hakbang sa itaas, maaari mong ipadala muli ang email. Tandaan na hindi nito ide-deactivate ang link sa lumang email."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Nagpadala ng email sa pag-sign in na may mga karagdagang tagubilin sa %@. Tingnan ang iyong email para makumpleto ang pag-sign in."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Naipadala na ang email sa pag-sign in"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr-CH.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr-CH.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..16bbcd32 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr-CH.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bienvenue"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Se connecter avec une adresse e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Saisissez votre adresse e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Cette adresse e-mail est incorrecte."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ce type de compte n'est pas compatible avec cette application"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Vous avez déjà un compte"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Vous avez déjà utilisé l'adresse e-mail %@. Connectez-vous avec %@ pour continuer."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Se connecter"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Saisissez votre mot de passe"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Vous devez indiquer un mot de passe."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "L'adresse e-mail et le mot de passe saisis ne correspondent pas."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Cette adresse e-mail ne correspond à aucun compte existant."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Cette adresse e-mail correspond à un compte qui a été désactivé."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Vous avez saisi un mot de passe incorrect un trop grand nombre de fois. Veuillez réessayer dans quelques minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Impossible de trouver un fournisseur pour %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Les adresses e-mail ne correspondent pas"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Récupérez votre mot de passe"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Les instructions relatives à la réinitialisation de votre mot de passe seront envoyées à cette adresse e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Consultez votre boîte de réception"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Suivez les instructions envoyées à l'adresse e-mail %@ pour récupérer votre mot de passe."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Créer un compte"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nom et prénom"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choisissez un mot de passe"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Conditions d'utilisation"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Règles de confidentialité"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "En continuant, vous acceptez les %@ et les %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Cette adresse e-mail est déjà utilisée par un autre compte."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Les mots de passe sécurisés comportent au moins six caractères et une combinaison de chiffres et de lettres."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "De trop nombreuses demandes de compte proviennent de votre adresse IP. Veuillez réessayer dans quelques minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Vous avez déjà utilisé l'adresse e-mail %@ pour vous connecter. Saisissez votre mot de passe pour ce compte."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annuler"; + +/* Back button title. */ +"Back" = "Retour"; + +/* Next button title. */ +"Next" = "Suivant"; + +/* Save button title. */ +"Save" = "Enregistrer"; + +/* Send button title. */ +"Send" = "Envoyer"; + +/* Resend button title. */ +"Resend" = "Renvoyer"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adresse e-mail"; + +/* Label next to a password text field. */ +"Password" = "Mot de passe"; + +/* Label next to a name text field. */ +"Name" = "Nom"; + +/* Alert title Error. */ +"Error" = "Erreur"; + +/* Alert button title Close. */ +"Close" = "Fermer"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sécurité"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Comptes associés"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nom"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adresse e-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Ajouter un mot de passe"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Modifier le mot de passe"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Se déconnecter"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Supprimer le compte"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Mot de passe oublié"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmez qu'il s'agit bien de vous"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Supprimer le compte ?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Vous devrez vous reconnecter pour finaliser cette opération."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Voulez-vous vraiment supprimer votre compte ?"; + +/* Text of Delete action button. */ +"Delete" = "Supprimer"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Supprimer le compte"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Cette action est irréversible"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Dissocier"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Compte associé"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Dissocier le compte ?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Vous ne pourrez plus utiliser votre compte pour vous connecter"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Dissocier le compte"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Pour modifier l'adresse e-mail associée à votre compte, vous devrez vous reconnecter."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Modifier l'adresse e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Modifier le nom"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Vous devrez vous reconnecter pour ajouter un mot de passe à votre compte."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Vous devrez vous reconnecter pour modifier le mot de passe de votre compte."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Ajouter un mot de passe"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Modifier le mot de passe"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adresse e-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Se connecter avec %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Saisissez votre nom"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Saisissez votre adresse e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Saisissez votre mot de passe"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nouveau mot de passe"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choisissez un mot de passe"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Vous ne parvenez pas à vous connecter ?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmez votre adresse e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Connecté"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Vous n'avez pas reçu l'e-mail ?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Essayez les solutions courantes suivantes : \n - Vérifiez que l'e-mail n'a pas été filtré ni marqué comme spam.\n - Vérifiez votre connexion Internet.\n - Vérifiez que votre adresse e-mail est correcte.\n - Vérifiez que votre boîte de réception n'est pas pleine et que les paramètres sont correctement définis.\n Si les étapes décrites ci-dessus n'ont pas résolu le problème, vous pouvez renvoyer l'e-mail. Sachez que le lien du premier e-mail sera alors désactivé."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Un e-mail de connexion avec des instructions supplémentaires a été envoyé à %@. Consultez cet e-mail pour vous connecter."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail de connexion envoyé"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..16bbcd32 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/fr.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bienvenue"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Se connecter avec une adresse e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Saisissez votre adresse e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Cette adresse e-mail est incorrecte."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ce type de compte n'est pas compatible avec cette application"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Vous avez déjà un compte"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Vous avez déjà utilisé l'adresse e-mail %@. Connectez-vous avec %@ pour continuer."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Se connecter"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Saisissez votre mot de passe"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Vous devez indiquer un mot de passe."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "L'adresse e-mail et le mot de passe saisis ne correspondent pas."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Cette adresse e-mail ne correspond à aucun compte existant."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Cette adresse e-mail correspond à un compte qui a été désactivé."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Vous avez saisi un mot de passe incorrect un trop grand nombre de fois. Veuillez réessayer dans quelques minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Impossible de trouver un fournisseur pour %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Les adresses e-mail ne correspondent pas"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Récupérez votre mot de passe"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Les instructions relatives à la réinitialisation de votre mot de passe seront envoyées à cette adresse e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Consultez votre boîte de réception"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Suivez les instructions envoyées à l'adresse e-mail %@ pour récupérer votre mot de passe."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Créer un compte"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nom et prénom"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choisissez un mot de passe"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Conditions d'utilisation"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Règles de confidentialité"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "En continuant, vous acceptez les %@ et les %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Cette adresse e-mail est déjà utilisée par un autre compte."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Les mots de passe sécurisés comportent au moins six caractères et une combinaison de chiffres et de lettres."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "De trop nombreuses demandes de compte proviennent de votre adresse IP. Veuillez réessayer dans quelques minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Vous avez déjà utilisé l'adresse e-mail %@ pour vous connecter. Saisissez votre mot de passe pour ce compte."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annuler"; + +/* Back button title. */ +"Back" = "Retour"; + +/* Next button title. */ +"Next" = "Suivant"; + +/* Save button title. */ +"Save" = "Enregistrer"; + +/* Send button title. */ +"Send" = "Envoyer"; + +/* Resend button title. */ +"Resend" = "Renvoyer"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adresse e-mail"; + +/* Label next to a password text field. */ +"Password" = "Mot de passe"; + +/* Label next to a name text field. */ +"Name" = "Nom"; + +/* Alert title Error. */ +"Error" = "Erreur"; + +/* Alert button title Close. */ +"Close" = "Fermer"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sécurité"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Comptes associés"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nom"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adresse e-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Ajouter un mot de passe"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Modifier le mot de passe"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Se déconnecter"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Supprimer le compte"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Mot de passe oublié"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmez qu'il s'agit bien de vous"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Supprimer le compte ?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Vous devrez vous reconnecter pour finaliser cette opération."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Voulez-vous vraiment supprimer votre compte ?"; + +/* Text of Delete action button. */ +"Delete" = "Supprimer"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Supprimer le compte"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Cette action est irréversible"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Dissocier"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Compte associé"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Dissocier le compte ?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Vous ne pourrez plus utiliser votre compte pour vous connecter"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Dissocier le compte"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Pour modifier l'adresse e-mail associée à votre compte, vous devrez vous reconnecter."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Modifier l'adresse e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Modifier le nom"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Vous devrez vous reconnecter pour ajouter un mot de passe à votre compte."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Vous devrez vous reconnecter pour modifier le mot de passe de votre compte."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Ajouter un mot de passe"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Modifier le mot de passe"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adresse e-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Se connecter avec %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Saisissez votre nom"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Saisissez votre adresse e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Saisissez votre mot de passe"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nouveau mot de passe"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choisissez un mot de passe"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Vous ne parvenez pas à vous connecter ?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmez votre adresse e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Connecté"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Vous n'avez pas reçu l'e-mail ?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Essayez les solutions courantes suivantes : \n - Vérifiez que l'e-mail n'a pas été filtré ni marqué comme spam.\n - Vérifiez votre connexion Internet.\n - Vérifiez que votre adresse e-mail est correcte.\n - Vérifiez que votre boîte de réception n'est pas pleine et que les paramètres sont correctement définis.\n Si les étapes décrites ci-dessus n'ont pas résolu le problème, vous pouvez renvoyer l'e-mail. Sachez que le lien du premier e-mail sera alors désactivé."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Un e-mail de connexion avec des instructions supplémentaires a été envoyé à %@. Consultez cet e-mail pour vous connecter."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail de connexion envoyé"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gsw.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gsw.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..3ad46398 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gsw.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Willkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Mit E-Mail-Adresse anmelden"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "E-Mail-Adresse eingeben"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Diese E-Mail-Adresse ist nicht korrekt."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Diese Art von Konto wird von dieser App nicht unterstützt"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Sie haben bereits ein Konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Sie haben %@ bereits verwendet. Melden Sie sich mit %@ an, um fortzufahren."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Anmelden"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Passwort eingeben"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Passwort darf nicht leer sein."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Die E-Mail-Adresse und das Passwort passen nicht zusammen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Diese E-Mail-Adresse passt zu keinem vorhandenen Konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Diese E-Mail-Adresse gehört zu einem Konto, das deaktiviert wurde."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Sie haben zu oft ein falsches Passwort eingegeben. Versuchen Sie es in einigen Minuten erneut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Anbieter für %@ wurde nicht gefunden."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-Mail-Adressen stimmen nicht überein"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Passwort wiederherstellen"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "In der an diese E-Mail-Adresse gesendeten Anleitung wird beschrieben, wie Sie Ihr Passwort zurücksetzen können."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Im Posteingang nachsehen"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Folgen Sie der an %@ gesendeten Anleitung, um Ihr Passwort zurückzusetzen."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Konto erstellen"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vor- und Nachname"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Passwort auswählen"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Nutzungsbedingungen"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Datenschutzerklärung"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Wenn Sie fortfahren, stimmen Sie unseren %@ und unserer %@ zu."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Die E-Mail-Adresse wird bereits von einem anderen Konto verwendet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Starke Passwörter umfassen mindestens sechs Zeichen und eine Mischung aus Buchstaben und Ziffern."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Von Ihrer IP-Adresse werden zu viele Kontoanfragen gesendet. Versuchen Sie es in einigen Minuten erneut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Sie haben bereits %@ zur Anmeldung verwendet. Geben Sie das Passwort für dieses Konto ein."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Abbrechen"; + +/* Back button title. */ +"Back" = "Zurück"; + +/* Next button title. */ +"Next" = "Weiter"; + +/* Save button title. */ +"Save" = "Speichern"; + +/* Send button title. */ +"Send" = "Senden"; + +/* Resend button title. */ +"Resend" = "Erneut senden"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-Mail-Adresse"; + +/* Label next to a password text field. */ +"Password" = "Passwort"; + +/* Label next to a name text field. */ +"Name" = "Name"; + +/* Alert title Error. */ +"Error" = "Fehler"; + +/* Alert button title Close. */ +"Close" = "Schließen"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sicherheit"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Verknüpfte Konten"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Name"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-Mail-Adresse"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Passwort hinzufügen"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Passwort ändern"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Abmelden"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Konto löschen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Passwort vergessen?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Identität bestätigen"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Konto löschen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Sie müssen sich erneut anmelden, um diese Aktion abzuschließen."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Hierdurch werden alle mit Ihrem Konto verknüpften Daten gelöscht. Dies kann nicht rückgängig gemacht werden. Möchten Sie Ihr Konto wirklich löschen?"; + +/* Text of Delete action button. */ +"Delete" = "Löschen"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Konto löschen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Diese Aktion kann nicht rückgängig gemacht werden"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Verknüpfung aufheben"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Verknüpftes Konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Verknüpfung des Kontos aufheben?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Sie können sich nicht mehr mit Ihrem Konto anmelden"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Verknüpfung des Kontos aufheben"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Wenn Sie die mit Ihrem Konto verknüpfte E-Mail-Adresse ändern möchten, müssen Sie sich erneut anmelden."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-Mail-Adresse bearbeiten"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Name bearbeiten"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Um Ihrem Konto ein Passwort hinzuzufügen, müssen Sie sich erneut anmelden."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Um das Passwort für Ihr Konto zu ändern, müssen Sie sich erneut anmelden."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Um das Passwort zu ändern, müssen Sie zuerst Ihr aktuelles Passwort eingeben."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Passwort hinzufügen"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Passwort ändern"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-Mail-Adresse"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Mit %@ anmelden"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Name eingeben"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "E-Mail-Adresse eingeben"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Passwort eingeben"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Neues Passwort"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Passwort auswählen"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Probleme bei der Anmeldung?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-Mail-Adresse bestätigen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Angemeldet."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Probleme beim Empfangen von E-Mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Versuchen Sie Folgendes: \n – Überprüfen Sie, ob die E-Mail als Spam markiert oder herausgefiltert wurde.\n – Überprüfen Sie Ihre Internetverbindung.\n – Überprüfen Sie die Schreibweise Ihrer E-Mail-Adresse.\n – Überprüfen Sie den Speicherplatz und weitere Einstellungen Ihres Posteingangs, die Probleme bereiten könnten.\n Sollte das Problem nach Ausführung der obigen Schritte weiterhin bestehen, können Sie sich die Anmelde-E-Mail noch einmal zusenden lassen. Hinweis: Der Link in der vorhergehenden E-Mail ist dann nicht mehr gültig."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Wir haben eine Anmelde-E-Mail mit zusätzlichen Informationen an %@ gesendet. Bitte öffnen Sie die E-Mail, um die Anmeldung abzuschließen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Anmelde-E-Mail gesendet"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gu.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gu.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..8e439e75 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/gu.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "સ્વાગત છે"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ઇમેઇલ વડે સાઇન ઇન કરો"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "તમારું ઇમેઇલ ઍડ્રેસ દાખલ કરો"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "તે ઇમેઇલ ઍડ્રેસ સાચું નથી."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "આ ઍપ્લિકેશન આ પ્રકારના એકાઉન્ટને સમર્થન આપતી નથી"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "તમારી પાસે પહેલેથી જ એક એકાઉન્ટ છે"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "તમે પહેલેથી %@નો ઉપયોગ કરી લીધો છે. આગળ વધવા માટે %@ વડે સાઇન ઇન કરો."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "સાઇન ઇન કરો"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "તમારો પાસવર્ડ દાખલ કરો"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "પાસવર્ડ દાખલ કરવો આવશ્યક છે."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "તમે દાખલ કરેલ ઇમેઇલ ઍડ્રેસ અને પાસવર્ડ મેળ ખાતો નથી."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "તે ઇમેઇલ ઍડ્રેસ અસ્તિત્વમાં છે તે એકાઉન્ટ સાથે મેળ ખાતું નથી."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "તે ઇમેઇલ ઍડ્રેસ અક્ષમ કરવામાં આવેલ એકાઉન્ટ માટે છે."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "તમે ઘણી બધી વખત ખોટો પાસવર્ડ દાખલ કર્યો છે. થોડીવારમાં ફરીથી પ્રયાસ કરો."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ માટે પ્રદાતા શોધી શકાતા નથી."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ઇમેઇલ મેળ ખાતા નથી"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "પાસવર્ડ પુનઃપ્રાપ્ત કરો"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "આ ઇમેઇલમાં મોકલવામાં આવેલ સૂચનાઓ મેળવો જે તમારો પાસવર્ડ કેવી રીતે રીસેટ કરવો તે સમજાવે છે."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "તમારું ઇમેઇલ ઍડ્રેસ તપાસો"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "તમારો પાસવર્ડ પુનઃપ્રાપ્ત કરવા માટે %@ પર મોકલેલ સૂચનાઓનું પાલન કરો."; + +/* Title for sign up screen. */ +"SignUpTitle" = "એકાઉન્ટ બનાવો"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "નામ અને અટક"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "પાસવર્ડ પસંદ કરો"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "સેવાની શરતો"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "ગોપનીયતા નીતિ"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "ચાલુ રાખીને, તમે સૂચવી રહ્યાં છો કે તમે અમારી %@ અને %@ને સ્વીકારો છો."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "આ ઇમેઇલ ઍડ્રેસ પહેલેથી જ અન્ય એકાઉન્ટ દ્વારા ઉપયોગમાં લેવાયેલ છે."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "સશક્ત પાસવર્ડ ઓછામાં ઓછા 6 અક્ષરો અને વર્ણ તથા સંખ્યાઓનાં સંયોજનનો હોવો જોઈએ."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "તમારા IP ઍડ્રેસ તરફથી એકાઉન્ટ માટે ઘણી બધી વિનંતી આવી રહી છે. થોડીવારમાં ફરી પ્રયાસ કરો."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "તમે સાઇન ઇન કરવા માટે %@નો પહેલાથી ઉપયોગ કરેલો છે. તે એકાઉન્ટ માટેનો તમારો પાસવર્ડ દાખલ કરો."; + +/* OK button title. */ +"OK" = "ઓકે"; + +/* Cancel button title. */ +"Cancel" = "રદ કરો"; + +/* Back button title. */ +"Back" = "પાછળ"; + +/* Next button title. */ +"Next" = "આગળ"; + +/* Save button title. */ +"Save" = "સાચવો"; + +/* Send button title. */ +"Send" = "મોકલો"; + +/* Resend button title. */ +"Resend" = "ફરી મોકલો"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ઇમેઇલ"; + +/* Label next to a password text field. */ +"Password" = "પાસવર્ડ"; + +/* Label next to a name text field. */ +"Name" = "નામ"; + +/* Alert title Error. */ +"Error" = "ભૂલ"; + +/* Alert button title Close. */ +"Close" = "બંધ કરો"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "પ્રોફાઇલ"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "સુરક્ષા"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "લિંક કરેલ એકાઉન્ટ"; + +/* Account Settings cell title Name. */ +"AS_Name" = "નામ"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ઇમેઇલ"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "પાસવર્ડ ઉમેરો"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "પાસવર્ડ બદલો"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "સાઇન આઉટ"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "એકાઉન્ટ કાઢી નાખો"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "પાસવર્ડ ભૂલી ગયા છો?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "ચકાસો કે આ તમે જ છો"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "એકાઉન્ટ કાઢી નાખીએ?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "આ તમારા એકાઉન્ટ સાથે સંકળાયેલ તમામ ડેટા કાઢી નાખશે અને તેને પૂર્વવત્ કરી શકાશે નહીં. તમારે આ ક્રિયા પૂર્ણ કરવા ફરીથી સાઇન ઇન કરવું જરૂરી છે"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "આ તમારા એકાઉન્ટ સાથે સંકળાયેલ તમામ ડેટા કાઢી નાખશે અને તેને પૂર્વવત્ કરી શકાશે નહીં. શું તમે ખરેખર તમારું એકાઉન્ટ કાઢી નાખવા માંગો છો?"; + +/* Text of Delete action button. */ +"Delete" = "કાઢી નાખો"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "એકાઉન્ટ કાઢી નાખો"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "આ ક્રિયા પૂર્વવત્ કરી શકાતી નથી"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "અનલિંક કરો"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "લિંક કરેલ એકાઉન્ટ"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "એકાઉન્ટને અનલિંક કરવું છે?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "હવે તમે તમારા એકાઉન્ટનો ઉપયોગ કરીને સાઇન ઇન કરી શકશો નહીં"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "એકાઉન્ટને અનલિંક કરો"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "તમારા એકાઉન્ટ સાથે સંકળાયેલ ઇમેઇલ ઍડ્રેસ બદલવા માટે, તમારે ફરીથી સાઇન ઇન કરવું જરૂરી છે."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "તમારો પાસવર્ડ બદલવા માટે, તમારે પહેલા તમારો વર્તમાન પાસવર્ડ દાખલ કરવો જરૂરી છે."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ઇમેઇલ સંપાદિત કરો"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "નામ સંપાદિત કરો"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "તમારા એકાઉન્ટમાં પાસવર્ડ ઉમેરવા માટે, તમારે ફરીથી સાઇન ઇન કરવું પડશે."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "તમારા એકાઉન્ટનો પાસવર્ડ બદલવા માટે, તમારે ફરીથી સાઇન ઇન કરવું પડશે."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "તમારો પાસવર્ડ બદલવા માટે, તમારે પહેલા તમારો વર્તમાન પાસવર્ડ દાખલ કરવો જરૂરી છે."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "પાસવર્ડ ઉમેરો"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "પાસવર્ડ બદલો"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ઇમેઇલ"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ વડે સાઇન ઇન કરો"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "તમારું નામ દાખલ કરો"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "તમારું ઇમેઇલ ઍડ્રેસ દાખલ કરો"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "તમારો પાસવર્ડ દાખલ કરો"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "નવો પાસવર્ડ"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "પાસવર્ડ પસંદ કરો"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "સાઇન ઇન કરવામાં સમસ્યા આવી રહી છે?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ઇમેઇલ કન્ફર્મ કરો"; + +/* Title of successfully signed in label. */ +"SignedIn" = "સાઇન ઇન કર્યું!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "ઇમેઇલ મેળવવામાં મુશ્કેલી આવે છે?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "આ સામાન્ય ઉકેલોને અજમાવી જુઓ: \n - તે ઇમેઇલ સ્પામ કે ફિલ્ટર કરેલ તરીકે ચિહ્નિત કર્યો હતો.કે કેમ તે ચેક કરો.\n - તમારું ઇન્ટરનેટ કનેક્શન ચેક કરો.\n - તમે તમારા ઇમેઇલની જોડણીમાં ભૂલ ન કરી હોવાનું ચેક કરો.\n - તમારી ઇનબૉક્સ સ્પેસ ભરાઈ ન ગઈ હોવાનું અથવા ઇનબૉક્સ સેટિંગ સંબંધિત અન્ય સમસ્યા ન હોવાનું.ચેક કરો.\n જો ઉપરોક્ત પગલાં કામ ન કરે, તો તમે ઇમેઇલ ફરીથી મોકલી શકો છો. નોંધ લેશો કે આને કારણે જૂના ઇમેઇલમાં રહેલી લિંક નિષ્ક્રિય થશે."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "વધારાની સૂચનાઓ ધરાવતો સાઇન-ઇન ઇમેઇલ %@ પર મોકલ્યો હતો. સાઇન-ઇન પૂર્ણ કરવા માટે તમારો ઇમેઇલ ચેક કરો."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "સાઇન ઇન ઇમેઇલ મોકલ્યો"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/he.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/he.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..a7085089 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/he.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "ברוכים הבאים"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "כניסה באמצעות אימייל"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "מה האימייל שלך?"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "כתובת האימייל שגויה."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "האפליקציה הזו לא תומכת בחשבונות מהסוג הזה"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "כבר יש לך חשבון"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "כבר השתמשת בכתובת %@. כדי להמשיך, עליך להיכנס באמצעות %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "כניסה"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "הסיסמה שלך כאן"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "לא הזנת סיסמה."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "אין התאמה בין כתובת האימייל לסיסמה שהזנת."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "אין חשבון המשויך לכתובת האימייל הזו."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "כתובת האימייל משויכת לחשבון שהושבת."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "הזנת סיסמה שגויה יותר מדי פעמים. אפשר יהיה לנסות שוב בעוד כמה דקות."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "לא מצאנו ספק ל-%@"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "כתובות האימייל לא זהות"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "שחזור הסיסמה"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "נוכל לשלוח לכתובת הזו הוראות לאיפוס הסיסמה."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "שלחנו לך אימייל"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "כדי לשחזר את הסיסמה, עליך לפעול לפי ההוראות ששלחנו לכתובת %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "יצירת חשבון"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "שם פרטי ומשפחה"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "הסיסמה שלך כאן"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "תנאים והגבלות"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "מדיניות פרטיות"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "המשך התהליך יפורש כהסכמתך ל%@ ול%@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "כתובת האימייל הזאת משויכת לחשבון אחר."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "סיסמה חזקה היא סיסמה באורך 6 תווים לפחות שמכילה אותיות ומספרים."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "קיבלנו יותר מדי בקשות ליצירת חשבון מכתובת ה-IP שלך. אפשר יהיה לנסות שוב בעוד כמה דקות."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "כבר השתמשת בכתובת %@ כדי להיכנס. עליך להזין את הסיסמה לחשבון המשויך אליה."; + +/* OK button title. */ +"OK" = "אישור"; + +/* Cancel button title. */ +"Cancel" = "ביטול"; + +/* Back button title. */ +"Back" = "הקודם"; + +/* Next button title. */ +"Next" = "הבא‏"; + +/* Save button title. */ +"Save" = "שמור"; + +/* Send button title. */ +"Send" = "שליחה"; + +/* Resend button title. */ +"Resend" = "שליחה מחדש"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "אימייל"; + +/* Label next to a password text field. */ +"Password" = "סיסמה"; + +/* Label next to a name text field. */ +"Name" = "שם"; + +/* Alert title Error. */ +"Error" = "שגיאה"; + +/* Alert button title Close. */ +"Close" = "סגור"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "פרופיל"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "אבטחה"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "חשבונות מקושרים"; + +/* Account Settings cell title Name. */ +"AS_Name" = "שם"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "אימייל"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "הוספת סיסמה"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "שינוי הסיסמה"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "יציאה"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "מחיקת החשבון"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "שכחת את הסיסמה?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "אנחנו צריכים לאמת את זהותך"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "למחוק את החשבון?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "הפעולה הזו תמחק את כל הנתונים המשויכים לחשבון, ולא ניתן לבטל אותה. כדי להשלים את המחיקה, צריך להיכנס מחדש"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "הפעולה הזו תמחק את כל הנתונים המשויכים לחשבון, ולא ניתן לבטל אותה. למחוק את החשבון?"; + +/* Text of Delete action button. */ +"Delete" = "מחק"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "מחיקת חשבון"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "לא ניתן לבטל את הפעולה הזו"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "בטל את הקישור"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "חשבון מקושר"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "לבטל את קישור החשבון?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "לא תהיה יותר אפשרות להיכנס באמצעות החשבון"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "ביטול הקישור של החשבון"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "כדי לשנות את כתובת האימייל המשויכת לחשבון, עליך להיכנס מחדש."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "כדי לשנות את הסיסמה, עליך להזין את הסיסמה הנוכחית."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "שינוי כתובת האימייל"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "עריכת שם"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "כדי להוסיף סיסמה לחשבון, עליך להיכנס מחדש."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "כדי לשנות את הסיסמה לחשבון, עליך להיכנס אליו."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "כדי לשנות את הסיסמה, עליך להזין את הסיסמה הנוכחית."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "הוספת סיסמה"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "שינוי הסיסמה"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "אימייל"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "כניסה באמצעות %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "הזן את שמך"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "האימייל שלך כאן"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "לא הזנת את הסיסמה"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "סיסמה חדשה"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "בחר סיסמה"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "לא מצליח להיכנס?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "אישור כתובת האימייל"; + +/* Title of successfully signed in label. */ +"SignedIn" = "בוצעה כניסה!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "נתקלת בבעיה בקבלת אימיילים?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "מומלץ לנסות את הפתרונות הבאים: \n - יש לבדוק אם האימייל סומן כספאם או סונן.\n - יש לבדוק את החיבור לאינטרנט.\n - יש לוודא שכתובת האימייל אויתה כהלכה.\n - יש לוודא שהשטח הפנוי בתיבת הדואר הנכנס אינו עומד להסתיים, או לבדוק בעיות אחרות שקשורות להגדרות של תיבת הדואר הנכנס.\n אם הבעיה נמשכת לאחר ביצוע השלבים המפורטים למעלה, אפשר לשלוח מחדש את האימייל. לתשומת ליבך: שליחת האימייל מחדש תשבית את הקישור באימייל הקודם."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "אימייל לכניסה לחשבון עם הוראות נוספות נשלח אל %@. יש לבדוק את תיבת הדואר הנכנס כדי להשלים את תהליך הכניסה."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "נשלח אימייל לכניסה לחשבון"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hi.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hi.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..06be9b3a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hi.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "आपका स्वागत है"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ईमेल से प्रवेश करें"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "अपना ईमेल डालें"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "वह ईमेल पता सही नहीं है."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "यह ऐप्लिकेशन इस प्रकार के खाते का समर्थन नहीं करता है"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "आपके पास पहले से ही एक खाता है"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "आपने पहले ही %@ का उपयोग कर लिया है. जारी रखने के लिए %@ से प्रवेश करें."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "प्रवेश करें"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "अपना पासवर्ड डालें"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "पासवर्ड खाली नहीं हो सकता."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "आपने जो ईमेल और पासवर्ड डाला है, उनका मिलान नहीं हो रहा है."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "वह ईमेल पता किसी मौजूदा खाते से मेल नहीं खाता है."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "यह ईमेल पता उस खाते का है जिसे अक्षम कर दिया गया है."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "आपने कई बार गलत पासवर्ड डाला. कुछ मिनटों में फिर से कोशिश करें."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ के लिए प्रदाता नहीं मिल सका."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ईमेल का मिलान नहीं हो रहा है"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "पासवर्ड फिर से प्राप्त करें"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "इस ईमेल पर भेजे गए निर्देश पाएं जो आपको अपना पासवर्ड रीसेट करना बताएंगे."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "अपना ईमेल जाँचें"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "अपना पासवर्ड फिर से पाने के लिए %@ पर भेजे गए निर्देशों का पालन करें."; + +/* Title for sign up screen. */ +"SignUpTitle" = "खाता बनाएं"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "नाम और उपनाम"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "पासवर्ड चुनें"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "सेवा की शर्तें"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "निजता नीति"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "जारी रखकर, आप यह बताते हैं कि आप हमारे %@ और %@ को स्वीकार करते हैं."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "कोई दूसरा खाता पहले से ही इस ईमेल पते का उपयोग कर रहा है."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "सशक्त पासवर्ड में कम से कम 6 वर्ण होने चाहिए और वे अक्षरों और नंबरों दोनों को मिलाकर बना होना चाहिए."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "आपके IP पते से बहुत अधिक खाता अनुरोध मिल रहे हैं. कुछ मिनटों में फिर से कोशिश करें."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "आपने पहले ही प्रवेश करने के लिए %@ का उपयोग कर लिया है. उस खाते के लिए अपना पासवर्ड डालें."; + +/* OK button title. */ +"OK" = "ठीक"; + +/* Cancel button title. */ +"Cancel" = "रद्द करें"; + +/* Back button title. */ +"Back" = "वापस जाएं"; + +/* Next button title. */ +"Next" = "अगला"; + +/* Save button title. */ +"Save" = "सहेजें"; + +/* Send button title. */ +"Send" = "भेजें"; + +/* Resend button title. */ +"Resend" = "फिर से भेजें"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ईमेल"; + +/* Label next to a password text field. */ +"Password" = "पासवर्ड"; + +/* Label next to a name text field. */ +"Name" = "नाम"; + +/* Alert title Error. */ +"Error" = "गड़बड़ी"; + +/* Alert button title Close. */ +"Close" = "बंद करें"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "प्रोफ़ाइल"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "सुरक्षा"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "लिंक किए गए खाते"; + +/* Account Settings cell title Name. */ +"AS_Name" = "नाम"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ईमेल"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "पासवर्ड जोड़ें"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "पासवर्ड बदलें"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "साइन आउट करें"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "खाता हटाएं"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "पासवर्ड भूल गए?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "पुष्टि करें कि यह आप ही हैं"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "खाता हटाएं?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "यह आपके खाते से संबंधित सभी डेटा मिटा देगा और इसे वापस नहीं पाया जा सकता है. इस कार्रवाई को पूरा करने के लिए आपको फिर से प्रवेश करना होगा"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "यह आपके खाते से संबंधित सभी डेटा मिटा देगा और इसे वापस नहीं पाया जा सकता है. क्या आप वाकई अपना खाता हटाना चाहते हैं?"; + +/* Text of Delete action button. */ +"Delete" = "हटाएं"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "खाता हटाएं"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "यह कार्रवाई पहले जैसी नहीं की जा सकती"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "अनलिंक करें"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "लिंक किया गया खाता"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "खाता अनलिंक करें?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "अब आप अपने खाते का उपयोग करके प्रवेश करने में सक्षम नहीं होंगे"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "खाता अनलिंक करें"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "अपने खाते से जुड़े ईमेल पते को बदलने के लिए, आपको फिर से प्रवेश करना होगा."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "अपना पासवर्ड बदलने के लिए, आपको पहले अपना मौजूदा पासवर्ड डालना होगा."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ईमेल संपादित करें"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "नाम संपादित करें"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "अपने खाते में पासवर्ड जोड़ने के लिए, आपको फिर से प्रवेश करना होगा."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "अपने खाते का पासवर्ड बदलने के लिए, आपको फिर से प्रवेश करना होगा."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "अपना पासवर्ड बदलने के लिए, आपको पहले अपना मौजूदा पासवर्ड डालना होगा."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "पासवर्ड जोड़ें"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "पासवर्ड बदलें"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ईमेल"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ से प्रवेश करें"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "अपना नाम डालें"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "अपना ईमेल डालें"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "अपना पासवर्ड डालें"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "नया पासवर्ड"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "पासवर्ड चुनें"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "प्रवेश करने में समस्या?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ईमेल की पुष्टि करें"; + +/* Title of successfully signed in label. */ +"SignedIn" = "साइन-इन हैं!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "क्या ईमेल मिलने में दिक्कत हो रही है?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "समस्या सुलझाने के ये सामान्य तरीके आज़माकर देखें: \n - देख लें कि ईमेल स्पैम फ़ोल्डर में तो नहीं चला गया या फ़िल्टर तो नहीं हो गया.\n - देख लें कि आपका इंटरनेट कनेक्शन चालू है या नहींं.\n - देख लें कि आपने ईमेल पते की वर्तनी (स्पेलिंग) गलत तो नहीं लिखी है.\n - देख लें कि आपका इनबॉक्स भर तो नहीं गया या इनबॉक्स सेटिंग से जुड़ी दूसरी समस्याएं तो नहीं हैं.\n अगर ऊपर दिए गए सुझावों से काम नहीं बनता है, तो आप फिर से ईमेल भेज सकते हैं. ध्यान दें कि ऐसा करने से पुराने ईमेल में भेजा गया लिंक काम करना बंद कर देगा."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "ज़्यादा निर्देशों वाला एक साइन-इन ईमेल %@ पर भेजा गया है. साइन-इन पूरा करने के लिए अपना ईमेल देखें."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "साइन-इन करने के लिंक वाला ईमेल भेज दिया गया"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hr.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hr.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..d386c7bc --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hr.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Dobro došli"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Prijava putem e-adrese"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Unesite svoju e-adresu"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Ta e-adresa nije točna"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ta vrsta računa nije podržana u ovoj aplikaciji"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Već imate račun"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Već ste upotrijebili e-adresu %@. Za nastavak se prijavite putem usluge %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Prijava"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Unesite zaporku"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Zaporka ne može biti prazna."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Unijeli ste e-adresu i zaporku koje se ne podudaraju."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Ta e-adresa ne pripada postojećem računu."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-adresa pripada računu koji je onemogućen."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Unijeli ste netočnu zaporku previše puta. Pokušajte ponovo za nekoliko minuta."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nije moguće pronaći davatelja usluga za %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-adrese se ne podudaraju"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Ponovno postavljanje zaporke"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Provjerite upute za ponovno postavljanje zaporke koje smo poslali na vašu e-adresu."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Provjerite e-poštu"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Slijedite upute za ponovno postavljanje zaporke koje smo poslali na e-adresu %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Izrada računa"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Ime i prezime"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Odaberite zaporku"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Uvjeti pružanja usluge"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Pravila o privatnosti"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Nastavkom upotrebe potvrđujete da prihvaćate odredbe koje sadrže naši %@ i %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ta e-adresa već pripada drugom računu."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Snažne zaporke sadrže bar 6 znakova koji su kombinacija slova i znamenki."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "S vaše je IP adrese došlo previše zahtjeva za izradu računa. Pokušajte ponovo za nekoliko minuta."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Za prijavu ste već upotrijebili e-adresu %@. Unesite zaporku za taj račun."; + +/* OK button title. */ +"OK" = "U redu"; + +/* Cancel button title. */ +"Cancel" = "Odustani"; + +/* Back button title. */ +"Back" = "Natrag"; + +/* Next button title. */ +"Next" = "Dalje"; + +/* Save button title. */ +"Save" = "Spremi"; + +/* Send button title. */ +"Send" = "Pošalji"; + +/* Resend button title. */ +"Resend" = "Pošalji ponovo"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-adresa"; + +/* Label next to a password text field. */ +"Password" = "Zaporka"; + +/* Label next to a name text field. */ +"Name" = "Naziv"; + +/* Alert title Error. */ +"Error" = "Pogreška"; + +/* Alert button title Close. */ +"Close" = "Zatvori"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sigurnost"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Povezani računi"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Naziv"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-adresa"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Dodavanje zaporke"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Promjena zaporke"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Odjava"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Brisanje računa"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Zaboravili ste zaporku?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Potvrdite svoj identitet"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Želite li izbrisati račun?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Izbrisat će se svi podaci povezani s vašim računom i to nećete moći poništiti. Da biste dovršili tu radnju, trebate se ponovo prijaviti"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Izbrisat će se svi podaci povezani s vašim računom i to nećete moći poništiti. Jeste li sigurni da želite izbrisati svoj račun?"; + +/* Text of Delete action button. */ +"Delete" = "Izbriši"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Izbriši račun"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Ta se radnja ne može poništiti"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Prekini vezu"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Povezani račun"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Prekinuti vezu s računom?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Više se nećete moći prijaviti svojim računom."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Prekidanje veze s računom"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Da biste promijenili e-adresu povezanu sa svojim računom, trebate se ponovo prijaviti."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Da biste promijenili zaporku, najprije trebate unijeti trenutačnu zaporku."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Uređivanje e-adrese"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Uređivanje naziva"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Da biste računu dodali zaporku, trebate se ponovo prijaviti."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Da biste promijenili zaporku za račun, trebate se ponovo prijaviti."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Da biste promijenili zaporku, najprije trebate unijeti trenutačnu zaporku."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Dodavanje zaporke"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Promjena zaporke"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-adresa"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Prijava putem usluge %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Unesite svoje ime"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Unesite svoju e-adresu"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Unesite zaporku"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nova zaporka"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Odaberite zaporku"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problem s prijavom?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potvrdite e-adresu"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Prijavljeni ste!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Ne dobivate e-poruke?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Isprobajte ova uobičajena rješenja: \n - Provjerite je li e-poruka filtrirana ili označena kao neželjena pošta.\n - Provjerite internetsku vezu.\n - Provjerite jeste li točno napisali e-adresu.\n - Provjerite ima li dovoljno prostora u vašem pretincu pristigle pošte ili je došlo do drugih problema povezanih s postavkama pretinca pristigle pošte.\n Ako se problem ne riješi pomoću koraka iznad, možete ponovo poslati e-poruku. Time će se deaktivirati veza u prethodnoj e-poruci."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "E-poruka za prijavu s dodatnim uputama poslana je na adresu %@. Provjerite e-poštu da biste dovršili prijavu."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-poruka za prijavu poslana"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hu.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hu.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..8ba2d81f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/hu.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Üdvözöljük!"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Bejelentkezés e-mail-fiókkal"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Adja meg az e-mail-címét"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Az e-mail-cím helytelen."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ezt a típusú fiókot az alkalmazás nem támogatja."; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Már rendelkezik fiókkal"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Már használta a következő e-mail-címet: %@. A folytatáshoz jelentkezzen be %@-fiókjával."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Bejelentkezés"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Adja meg a jelszót"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "A jelszó mező nem lehet üres."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "A megadott e-mail-cím és jelszó nem egyezik."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Ehhez az e-mail-címhez egyetlen meglévő fiók sem tartozik."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Ez az e-mail-cím egy letiltott fiókhoz tartozik."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Túl sokszor adott meg hibás jelszót. Néhány perc múlva próbálja újra."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nem találjuk a következőhöz tartozó szolgáltatót: %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Az e-mail-címek nem egyeznek."; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Jelszó visszaállítása"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Olvassa el az e-mailben elküldött utasításokat, amelyekből megtudhatja, hogyan állíthatja vissza a jelszavát."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Ellenőrizze az e-mailjeit."; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "A jelszó visszaállításához kövesse az ide (%@) elküldött utasításokat."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Fiók létrehozása"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Utónév és vezetéknév"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Válasszon jelszót"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Általános Szerződési Feltételek"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Adatvédelmi irányelvek"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "A folytatással kinyilvánítja, hogy elfogadja %@ és %@ dokumentumainkat."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Az e-mail-cím egy másik fióknál már használatban van."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Az erős jelszavak legalább 6 karakterből állnak, valamint betűket és számokat egyaránt tartalmaznak."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Az Ön IP-címéről túl sok fiókkérelem érkezik. Néhány perc múlva próbálja újra."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ezt az e-mail-fiókot (%@) már használta bejelentkezésre. Adja meg a fiókhoz tartozó jelszót."; + +/* OK button title. */ +"OK" = "Rendben"; + +/* Cancel button title. */ +"Cancel" = "Mégse"; + +/* Back button title. */ +"Back" = "Vissza"; + +/* Next button title. */ +"Next" = "Következő"; + +/* Save button title. */ +"Save" = "Mentés"; + +/* Send button title. */ +"Send" = "Küldés"; + +/* Resend button title. */ +"Resend" = "Újraküldés"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Jelszó"; + +/* Label next to a name text field. */ +"Name" = "Név"; + +/* Alert title Error. */ +"Error" = "Hiba"; + +/* Alert button title Close. */ +"Close" = "Bezárás"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Biztonság"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Összekapcsolt fiókok"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Név"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Jelszó hozzáadása"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Jelszó módosítása"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Kijelentkezés"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Fiók törlése"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Elfelejtette a jelszavát?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Igazolja, hogy Ön az"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Fiók törlése?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Ezzel az összes fiókadatát törli, és ezt a műveletet nem vonhatja vissza. A művelet végrehajtásához újra be kell jelentkeznie."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Ezzel az összes fiókadatát törli, és ezt a műveletet nem vonhatja vissza. Biztosan törölni szeretné a fiókját?"; + +/* Text of Delete action button. */ +"Delete" = "Törlés"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Fiók törlése"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "A művelet nem vonható vissza."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Leválasztás"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Összekapcsolt fiók"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Leválasztja a fiókot?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Többé nem fog tudni bejelentkezni a fiókkal."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Fiók leválasztása"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "A fiókjához tartozó e-mail-cím módosításához újra be kell jelentkeznie."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "A jelszó módosításához előbb meg kell adnia a jelenlegi jelszavát."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-mail szerkesztése"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Név szerkesztése"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Ha fiókjához jelszót szeretne hozzáadni, újra be kell jelentkeznie."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Fiókja jelszavának módosításához újra be kell jelentkeznie."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "A jelszó módosításához előbb meg kell adnia a jelenlegi jelszavát."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Jelszó hozzáadása"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Jelszó módosítása"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Bejelentkezés a következővel: %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Írja be a nevét"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Adja meg az e-mail-címét"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Adja meg a jelszót"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Új jelszó"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Válasszon jelszót"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problémái vannak a bejelentkezéssel?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-mail megerősítése"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Sikeres bejelentkezés!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Gondja van az e-mailek fogadásával?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Próbálja ki ezeket az általános problémamegoldó lépéseket: \n – Nézze meg, hogy nem került-e az e-mail a spameket tartalmazó mappába, vagy nem szűrte-e ki a levelezőrendszer.\n – Ellenőrizze az internetkapcsolatot.\n – Ellenőrizze, hogy helyesen adta-e meg az e-mail-címét.\n – Ellenőrizze, hogy a beérkező leveleket tartalmazó mappa nem telt-e meg, vagy nincs-e más, a mappával kapcsolatos probléma.\n Ha a fenti lépések nem végrehajtása nem járt eredménnyel, küldje el újra az e-mailt. Ne feledje, hogy ezzel deaktiválja az előző e-mailben szereplő linket."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "A további utasításokat tartalmazó bejelentkezési e-mailt elküldtük ide: %@. A bejelentkezés befejezéséhez keresse meg az e-mailjei között."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Elküldtük a bejelentkezési e-mailt"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/id.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/id.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..c8b3e145 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/id.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Selamat datang"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Login dengan email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Masukkan email Anda"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Alamat email yang dimasukkan salah."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Jenis akun ini tidak didukung oleh aplikasi ini"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Anda sudah memiliki akun"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Anda telah menggunakan %@. Login dengan %@ untuk melanjutkan."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Login"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Masukkan sandi"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Sandi tidak boleh kosong."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Email dan sandi yang Anda masukkan tidak cocok."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Alamat email tidak cocok dengan akun yang ada."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Akun yang sesuai dengan alamat email tersebut sudah dinonaktifkan."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Anda sudah terlalu sering memasukkan sandi yang salah. Coba beberapa menit lagi."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Tidak dapat menemukan provider untuk %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Email tidak cocok"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Pulihkan sandi"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Dapatkan petunjuk yang dikirimkan ke email ini yang menjelaskan cara menyetel ulang sandi Anda."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Periksa email Anda"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Ikuti petunjuk yang dikirim ke %@ untuk memulihkan sandi Anda."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Buat akun"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nama depan & nama belakang"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Pilih sandi"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Persyaratan Layanan"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Kebijakan Privasi"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Dengan melanjutkan, Anda menyatakan persetujuan atas %@ dan %@ kami."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Alamat email ini sudah digunakan oleh akun lain."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Sandi yang kuat harus memiliki minimal 6 karakter dan merupakan kombinasi huruf dan angka."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Terlalu banyak permintaan akun yang berasal dari alamat IP Anda. Coba beberapa menit lagi."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Anda telah menggunakan %@ untuk login. Masukkan sandi untuk akun tersebut."; + +/* OK button title. */ +"OK" = "Oke"; + +/* Cancel button title. */ +"Cancel" = "Batal"; + +/* Back button title. */ +"Back" = "Kembali"; + +/* Next button title. */ +"Next" = "Berikutnya"; + +/* Save button title. */ +"Save" = "Simpan"; + +/* Send button title. */ +"Send" = "Kirim"; + +/* Resend button title. */ +"Resend" = "Kirim ulang"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Sandi"; + +/* Label next to a name text field. */ +"Name" = "Nama"; + +/* Alert title Error. */ +"Error" = "Error"; + +/* Alert button title Close. */ +"Close" = "Tutup"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Keamanan"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Akun Tertaut"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nama"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Tambahkan sandi"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Ubah sandi"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Logout"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Hapus Akun"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Lupa sandi?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifikasi bahwa itu Anda"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Hapus Akun?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Tindakan ini akan menghapus semua data yang terkait dengan akun Anda, dan tidak dapat diurungkan. Anda harus login kembali untuk menyelesaikan tindakan ini"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Tindakan ini akan menghapus semua data yang terkait dengan akun Anda, dan tidak dapat diurungkan. Yakin ingin menghapus akun?"; + +/* Text of Delete action button. */ +"Delete" = "Hapus"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Hapus akun"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tindakan ini tidak dapat diurungkan"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Batalkan tautan"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Akun tertaut"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Batalkan tautan akun?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Anda tidak dapat lagi login menggunakan akun Anda"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Batalkan tautan akun"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Untuk mengubah alamat email yang dikaitkan dengan akun, Anda perlu melakukan login kembali."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Untuk mengubah sandi, Anda harus memasukkan sandi saat ini terlebih dahulu."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit nama"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Untuk menambahkan sandi ke akun, Anda harus login kembali."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Untuk mengubah sandi akun, Anda harus login kembali."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Untuk mengubah sandi, Anda harus memasukkan sandi saat ini terlebih dahulu."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Tambahkan sandi"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Ubah sandi"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Login dengan %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Masukkan nama Anda"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Masukkan email Anda"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Masukkan sandi"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Sandi baru"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Pilih sandi"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Terjadi masalah saat login?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Konfirmasi Email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Telah login"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Ada masalah dalam mendapatkan email?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Cobalah perbaikan umum berikut: \n - Periksa apakah email ditandai sebagai spam atau difilter.\n - Periksa koneksi internet Anda.\n - Pastikan Anda tidak salah mengeja email Anda.\n - Pastikan masih ada ruang di kotak masuk Anda, atau periksa masalah terkait setelan kotak masuk lainnya.\n Jika langkah-langkah di atas tidak memecahkan masalah, Anda dapat mengirim ulang email tersebut. Perlu diperhatikan bahwa tindakan ini akan menonaktifkan link di email lama."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Email login dengan petunjuk tambahan telah dikirim ke %@. Buka email Anda untuk menyelesaikan proses login."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Email Login Terkirim"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/it.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/it.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..069a96cb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/it.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Benvenuto"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Accedi con l'indirizzo email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Inserisci l'indirizzo email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "L'indirizzo email non è corretto."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Questo tipo di account non è supportato da questa applicazione"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Hai già un account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Hai già utilizzato %@. Accedi con %@ per continuare."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Accedi"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Inserisci la password"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "La password non può essere vuota."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "L’indirizzo email e la password non corrispondono."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "L'indirizzo email non corrisponde a un account esistente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "L'indirizzo email è relativo a un account che è stato disattivato."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Hai effettuato troppi tentativi con una password errata. Riprova tra qualche minuto."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Impossibile trovare il provider per %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Gli indirizzi email non corrispondono"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recupera la password"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Ricevi le istruzioni a questo indirizzo email che spiegano come reimpostare la password."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Controlla la tua casella di posta"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Segui le istruzioni inviate all'indirizzo %@ per recuperare la password."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Crea account"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nome e cognome"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Scegli password"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Termini di servizio"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Norme sulla privacy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Se continui, accetti i nostri %@ e le nostre %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "L'indirizzo email è già utilizzato da un altro account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Una password efficace è composta da almeno 6 caratteri e contiene una combinazione di lettere e numeri."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Troppe richieste di account provenienti dal tuo indirizzo IP. Riprova tra qualche minuto."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Hai già utilizzato %@ per accedere. Inserisci la tua password per tale account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annulla"; + +/* Back button title. */ +"Back" = "Indietro"; + +/* Next button title. */ +"Next" = "Avanti"; + +/* Save button title. */ +"Save" = "Salva"; + +/* Send button title. */ +"Send" = "Invia"; + +/* Resend button title. */ +"Resend" = "Invia di nuovo"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Password"; + +/* Label next to a name text field. */ +"Name" = "Nome"; + +/* Alert title Error. */ +"Error" = "Errore"; + +/* Alert button title Close. */ +"Close" = "Chiudi"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profilo"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sicurezza"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Account collegati"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nome"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Aggiungi password"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Cambia password"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Esci"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Elimina account"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Password dimenticata?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifica che sei tu"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Vuoi eliminare l'account?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "L'operazione cancellerà tutti i dati associati al tuo account e non può essere annullata. Devi accedere nuovamente per completarla."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "L'operazione cancellerà tutti i dati associati al tuo account e non può essere annullata. Vuoi eliminare il tuo account?"; + +/* Text of Delete action button. */ +"Delete" = "Elimina"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Elimina account"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Questa azione non può essere annullata"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Scollega"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Account collegato"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Vuoi scollegare l'account?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Non potrai accedere utilizzando il tuo account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Scollega account"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Per modificare l'indirizzo email associato al tuo account, devi accedere di nuovo."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Per modificare la password, devi prima inserire la password corrente."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Modifica email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Modifica nome"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Per aggiungere la password al tuo account, devi accedere di nuovo."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Per modificare la password del tuo account, devi accedere di nuovo."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Per modificare la password, devi prima inserire la password corrente."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Aggiungi password"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Cambia password"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Accedi con %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Inserisci il tuo nome"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Inserisci l'indirizzo email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Inserisci la password"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nuova password"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Scegli password"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problemi di accesso?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Conferma email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Accesso eseguito"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Non ricevi l'email?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prova le seguenti soluzioni comuni: \n - Verifica se l'email è stata contrassegnata come spam o è stata filtrata.\n - Controlla la connessione Internet.\n - Verifica di aver digitato correttamente l'indirizzo email.\n - Verifica che vi sia ancora spazio disponibile nella Posta in arrivo o che non vi siano altri problemi legati alle impostazioni della Posta in arrivo.\n Se le procedure descritte sopra non hanno risolto il problema, puoi inviare nuovamente l'email. Tieni presente che questo disattiverà il link contenuto nell'email precedente."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Un'email di accesso con ulteriori istruzioni è stata inviata all'indirizzo %@. Controlla la tua casella di posta per completare l'accesso."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Email di accesso inviata"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ja.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ja.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..94eec9d8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ja.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "ようこそ"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "メールアドレスでログイン"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "メールアドレスを入力してください"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "メールアドレスが正しくありません。"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "このタイプのアカウントはこのアプリでサポートされていません"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "アカウントをすでにお持ちです"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "%@ をすでに使用しています。%@ でログインして続行してください。"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "ログイン"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "パスワードを入力"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "パスワードは空白にできません。"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "入力したメールアドレスとパスワードが一致しません。"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "メールアドレスが既存のアカウントと一致しません。"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "これは無効になったアカウントのメールアドレスです。"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "正しくないパスワードを何度も入力しています。しばらくしてからもう一度お試しください。"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ のプロバイダが見つかりません。"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "メールアドレスが一致しません"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "パスワードの復元"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "このメールアドレスに送信された、パスワードの復元方法をご確認ください。"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "メールをご確認ください"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "%@ に送信された手順に沿ってパスワードを復元します。"; + +/* Title for sign up screen. */ +"SignUpTitle" = "アカウントの作成"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "あなたの名前"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "パスワードを設定"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "利用規約"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "プライバシー ポリシー"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "続行すると、%@と%@に同意したことになります。"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "このメールアドレスは他のアカウントによってすでに使用されています。"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "6 文字以上で、文字と数字を組み合わせた安全なパスワードを設定してください。"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "この IP アドレスから多くのアカウント リクエストが送信されています。しばらくしてからもう一度お試しください。"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "すでに %@ を使用してログインしています。このアカウントのパスワードを入力してください。"; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "キャンセル"; + +/* Back button title. */ +"Back" = "戻る"; + +/* Next button title. */ +"Next" = "次へ"; + +/* Save button title. */ +"Save" = "保存"; + +/* Send button title. */ +"Send" = "送信"; + +/* Resend button title. */ +"Resend" = "再送信"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "メール"; + +/* Label next to a password text field. */ +"Password" = "パスワード"; + +/* Label next to a name text field. */ +"Name" = "名前"; + +/* Alert title Error. */ +"Error" = "エラー"; + +/* Alert button title Close. */ +"Close" = "閉じる"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "プロフィール"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "セキュリティ"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "リンクされたアカウント"; + +/* Account Settings cell title Name. */ +"AS_Name" = "名前"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "メールアドレス"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "パスワードの追加"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "パスワードの変更"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "ログアウト"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "アカウントの削除"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "パスワードをお忘れの場合"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "ご本人確認"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "アカウントを削除しますか?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "この操作を行うと、アカウントに関連付けられたすべてのデータが削除され、元に戻すことはできません。この操作を完了させるには、再度ログインする必要があります。"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "この操作を行うと、アカウントに関連付けられたすべてのデータが削除され、元に戻すことはできません。アカウントを削除してもよろしいですか?"; + +/* Text of Delete action button. */ +"Delete" = "削除"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "アカウントの削除"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "この操作は元に戻せません"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "リンクを解除"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "リンクされたアカウント"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "アカウントのリンクを解除しますか?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "このアカウントを使用してログインできなくなります"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "アカウントのリンク解除"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "アカウントに関連付けられているメールアドレスを変更するには、再度ログインする必要があります。"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "パスワードを変更するには、まず現在のパスワードを入力する必要があります。"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "メールアドレスの編集"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "名前の編集"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "アカウントにパスワードを追加するには、再度ログインする必要があります。"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "アカウントのパスワードを変更するには、再度ログインする必要があります。"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "パスワードを変更するには、まず現在のパスワードを入力する必要があります。"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "パスワードの追加"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "パスワードの変更"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "メールアドレス"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ でログイン"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "名前を入力"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "メールアドレスを入力"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "パスワードを入力"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "新しいパスワード"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "パスワードを設定"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "ログインできない場合"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "メールの確認"; + +/* Title of successfully signed in label. */ +"SignedIn" = "ログインしました"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "メールが受信できない場合"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "以下の一般的な解決方法をお試しください。\n - メールがスパムに分類されたりフィルタされたりしていないか確認する。\n - インターネットの接続を確認する。\n - メールアドレスのスペルに誤りがないか確認する。\n - 受信トレイの容量不足や、設定関連のその他の問題がないか確認する。\n 上記の手順で解決しなかった場合はメールを再送信できます。メールを再送信すると、前回のメールに記載されたリンクは無効になります。"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "詳細な手順を記載したログインメールを %@ に送信しました。メールを確認してログインを完了してください。"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "ログインメールを送信しました"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/kn.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/kn.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..cd6787fb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/kn.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "ಸ್ವಾಗತ"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ಇಮೇಲ್ ಜೊತೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ನಮೂದಿಸಿ"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "ಆ ಇಮೇಲ್ ವಿಳಾಸವು ಸರಿಯಾಗಿಲ್ಲ."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಈ ರೀತಿಯ ಖಾತೆಯನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "ನೀವು ಈಗಾಗಲೇ ಖಾತೆಯನ್ನು ಹೊಂದಿರುವಿರಿ"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "ನೀವು ಈಗಾಗಲೇ %@ ನ್ನು ಬಳಸಿದ್ದೀರಿ. ಮುಂದುವರಿಸಲು %@ ಜೊತೆ ಸೈನ್ ಇನ್ ಮಾಡಿ."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "ಸೈನ್ ಇನ್‌"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "ಪಾಸ್‌ವರ್ಡ್‌ ಖಾಲಿ ಇರುವಂತಿಲ್ಲ."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "ನೀವು ನಮೂದಿಸಿರುವ ಇಮೇಲ್‌ ಮತ್ತು ಪಾಸ್‌ವರ್ಡ್‌ ಹೊಂದಾಣಿಕೆಯಾಗಿಲ್ಲ."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "ಆ ಇಮೇಲ್‌ ವಿಳಾಸವು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಖಾತೆಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "ಖಾತೆಗೆ ಆ ಇಮೇಲ್‌ ವಿಳಾಸವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "ಹಲವು ಬಾರಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ ನಮೂದಿಸಿರುವಿರಿ. ಕೆಲವು ನಿಮಿಷಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ ಗಾಗಿ ಪೂರೈಕೆದಾರರನ್ನು ಹುಡಕಲಾಗಲಿಲ್ಲ"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ಇಮೇಲ್‌ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "ಪಾಸ್‌ವರ್ಡ್ ಹಿಂಪಡೆಯಿರಿ"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಲು ಆ ಇಮೇಲ್‌ಗೆ ಕಳುಹಿಸಿರುವ ಸೂಚನೆಗಳನ್ನು ಪಡೆಯಿರಿ."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "ನಿಮ್ಮ ಇಮೇಲ್‌ ಅನ್ನು ಪರಿಶೀಲಿಸಿ"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಪಡೆಯಲು %@ ಗೆ ಕಳುಹಿಸಲಾದ ಸೂಚನೆಗಳನ್ನು ಅನುಸರಿಸಿ."; + +/* Title for sign up screen. */ +"SignUpTitle" = "ಖಾತೆ ರಚಿಸಿ"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "ಮೊದಲ ಮತ್ತು ಕೊನೆಯ ಹೆಸರು"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಆರಿಸಿ"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "ಸೇವಾ ನಿಯಮಗಳು"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "ಗೌಪ್ಯತೆ ನೀತಿ"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "ಮುಂದುವರಿಸುವ ಮೂಲಕ, ನೀವು ನಮ್ಮ %@ ಮತ್ತು %@ ಸ್ವೀಕರಿಸುತ್ತೀರಿ ಎಂದು ನೀವು ಸೂಚಿಸುತ್ತಿರುವಿರಿ"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "ಇಮೇಲ್‌ ವಿಳಾಸವು ಈಗಾಗಲೇ ಮತ್ತೊಂದು ಖಾತೆಗೆ ಬಳಸಲಾಗಿದೆ."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "ಪ್ರಬಲವಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಕನಿಷ್ಠ ಅಕ್ಷರಗಳನ್ನಾದರೂ ಹಾಗೂ ಮಿಕ್ಸ್‌ ಅಕ್ಷರಗಳು ಮತ್ತು ಸಂಖ್ಯೆಗಳು ಇರಬೇಕು."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "ನಿಮ್ಮ ಐಪಿ ವಿಳಾಸದಿಂದ ಅತಿ ಹೆಚ್ಚು ಖಾತೆ ಕೋರಿಕೆಗಳು ಬರುತ್ತಿವೆ. ಕೆಲವು ನಿಮಿಷಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "ನೀವು ಈಗಾಗಲೇ ಸೈನ್ ಇನ್ ಮಾಡಲು %@ ನ್ನು ಬಳಸಿದ್ದೀರ. ಆ ಖಾತೆಗೆ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ನಮೂದಿಸಿ."; + +/* OK button title. */ +"OK" = "ಸರಿ"; + +/* Cancel button title. */ +"Cancel" = "ರದ್ದುಮಾಡಿ"; + +/* Back button title. */ +"Back" = "ಹಿಂದೆ"; + +/* Next button title. */ +"Next" = "ಮುಂದೆ"; + +/* Save button title. */ +"Save" = "ಉಳಿಸಿ"; + +/* Send button title. */ +"Send" = "ಕಳುಹಿಸಿ"; + +/* Resend button title. */ +"Resend" = "ಪುನಃಕಳುಹಿಸಿ"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ಇಮೇಲ್"; + +/* Label next to a password text field. */ +"Password" = "ಪಾಸ್‌ವರ್ಡ್"; + +/* Label next to a name text field. */ +"Name" = "ಹೆಸರು"; + +/* Alert title Error. */ +"Error" = "ದೋಷ"; + +/* Alert button title Close. */ +"Close" = "ಮುಚ್ಚಿ"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "ಪ್ರೊಫೈಲ್"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "ಭದ್ರತೆ"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "ಲಿಂಕ್‌ ಮಾಡಲಾದ ಖಾತೆಗಳು"; + +/* Account Settings cell title Name. */ +"AS_Name" = "ಹೆಸರು"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ಇಮೇಲ್"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "ಪಾಸ್‌ವರ್ಡ್‌ ಸೇರಿಸಿ"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "ಪಾಸ್‌ವರ್ಡ್ ಬದಲಿಸಿ"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "ಸೈನ್ ಔಟ್"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "ಖಾತೆಯನ್ನು ಅಳಿಸಿ"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "ಪಾಸ್‌ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "ಅದು ನೀವೇ ಎಂದು ಪರಿಶೀಲಿಸಿ"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "ಖಾತೆಯನ್ನು ಅಳಿಸುವುದೇ?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಇದು ಅಳಿಸಿಹಾಕುತ್ತದೆ ಮತ್ತು ರದ್ದುಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನೀವು ಈ ಕ್ರಿಯೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ಪುನಃ ಸೈನ್‌ ಇನ್‌ ಮಾಡಬೇಕಾಗುತ್ತದೆ."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಬಂಧಿಸಿದ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಇದು ಅಳಿಸಿಹಾಕುತ್ತದೆ ಮತ್ತು ರದ್ದುಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಈ ಖಾತೆಯನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?"; + +/* Text of Delete action button. */ +"Delete" = "ಅಳಿಸಿ"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "ಖಾತೆಯನ್ನು ಅಳಿಸಿ"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "ಈ ಕ್ರಿಯೆಯನ್ನು ರದ್ದುಪಡಿಸಲಾಗುವುದಿಲ್ಲ."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "ಅನ್‌ಲಿಂಕ್"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "ಲಿಂಕ್‌ ಮಾಡಿದ ಖಾತೆ"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "ಖಾತೆಯ ಲಿಂಕ್‌ ರದ್ದುಗೊಳಿಸುವುದೇ?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "ಇನ್ನು ಮುಂದೆ ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ಸೈನ್‌ ಇನ್‌ ಮಾಡಲಾಗುವುದಿಲ್ಲ"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "ಖಾತೆಯ ಲಿಂಕ್‌ ರದ್ದುಮಾಡಿ"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಬಂಧಿಸಿದ ಇಮೇಲ್‌ ವಿಳಾಸವನ್ನು ಬದಲಿಸಲು, ನೀವು ಪುನಃ ಸೈನ್‌ ಇನ್‌ ಮಾಡಬೇಕಾಗುತ್ತದೆ."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಬದಲಿಸಲು, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ನೀವು ಮೊದಲು ನಮೂದಿಸಬೇಕಾಗಿದೆ."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ಇಮೇಲ್‌ ಎಡಿಟ್‌ ಮಾಡಿ"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "ಹೆಸರನ್ನು ಎಡಿಟ್ ಮಾಡಿ"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "ನಿಮ್ಮ ಖಾತೆಗೆ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಸೇರಿಸಲು, ನೀವು ಪುನಃ ಸೈನ್‌ ಇನ್‌ ಮಾಡಬೇಕಾಗುತ್ತದೆ."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "ನಿಮ್ಮ ಖಾತೆಗೆ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಬದಲಿಸಲು, ನೀವು ಪುನಃ ಸೈನ್‌ ಇನ್‌ ಮಾಡಬೇಕಾಗುತ್ತದೆ."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಬದಲಿಸಲು, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ನೀವು ಮೊದಲು ನಮೂದಿಸಬೇಕಾಗಿದೆ."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "ಪಾಸ್‌ವರ್ಡ್‌ ಸೇರಿಸಿ"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "ಪಾಸ್‌ವರ್ಡ್ ಬದಲಿಸಿ"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ಇಮೇಲ್"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ ಮೂಲಕ ಸೈನ್‌ ಇನ್ ಮಾಡಿ"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "ನಿಮ್ಮ ಹೆಸರು ನಮೂದಿಸಿ"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ನಮೂದಿಸಿ"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "ಹೊಸ ಪಾಸ್‌ವರ್ಡ್"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಆರಿಸಿ"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "ಸೈನ್ ಇನ್ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ ಇದೆಯೇ?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ಇಮೇಲ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ"; + +/* Title of successfully signed in label. */ +"SignedIn" = "ಸೈನ್ ಇನ್ ಆಗಿದೆ!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "ಇಮೇಲ್‌ಗಳನ್ನು ಪಡೆಯುವಲ್ಲಿ ಸಮಸ್ಯೆ ಉಂಟಾಗುತ್ತಿದೆಯೇ?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "ಈ ಸಾಮಾನ್ಯ ಪರಿಹಾರಗಳನ್ನು ಪ್ರಯತ್ನಿಸಿ: \n - ಇಮೇಲ್ ಅನ್ನು ಸ್ಪ್ಯಾಮ್ ಎಂದು ಗುರುತು ಮಾಡಲಾಗಿದೆಯೇ ಅಥವಾ ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n - ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ.\n - ನಿಮ್ಮ ಇಮೇಲ್‌ನ ಕಾಗುಣಿತವನ್ನು ಸರಿಯಾಗಿ ನಮೂದಿಸಿರುವಿರಾ ಎಂಬುದನ್ನು ಪರಿಶೀಲಿಸಿ.\n - ನಿಮ್ಮ ಇನ್‌ಬಾಕ್ಸ್ ಸಂಗ್ರಹಣೆಯು ಭರ್ತಿಯಾಗದಿರುವುದನ್ನು ಅಥವಾ ಇತರ ಇನ್‌ಬಾಕ್ಸ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಸಂಬಂಧಿಸಿದ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಶೀಲಿಸಿ.\n ಮೇಲಿನ ಹಂತಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸದಿದ್ದಲ್ಲಿ, ನೀವು ಇಮೇಲ್ ಅನ್ನು ಪುನಃ ಕಳುಹಿಸಬಹುದು. ಇದು ಹಳೆಯ ಇಮೇಲ್‌ನಲ್ಲಿರುವ ಲಿಂಕ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಗಮನಿಸಿ."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "%@ ಇಮೇಲ್‌ಗೆ ಹೆಚ್ಚುವರಿ ಸೂಚನೆಗಳನ್ನು ಹೊಂದಿರುವ ಸೈನ್-ಇನ್ ಇಮೇಲ್ ಅನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ. ಸೈನ್-ಇನ್ ಪೂರ್ಣಗೊಳಿಸಲು ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "ಸೈನ್-ಇನ್ ಇಮೇಲ್ ಕಳುಹಿಸಲಾಗಿದೆ"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ko.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ko.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..2fe62e7d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ko.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "시작"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "이메일로 로그인"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "이메일 입력"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "이메일 주소가 잘못되었습니다."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "이 앱에서 지원하지 않는 계정 유형입니다."; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "계정이 이미 있음"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "%@을(를) 이미 사용하고 있습니다. 계속하려면 %@(으)로 로그인하세요."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "로그인"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "비밀번호를 입력하세요."; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "비밀번호는 비워둘 수 없습니다."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "입력한 이메일과 비밀번호가 일치하지 않습니다."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "이메일 주소가 기존 계정과 일치하지 않습니다."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "사용 중지된 계정의 이메일 주소입니다."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "비밀번호 입력 오류 횟수를 초과했습니다. 잠시 후에 다시 시도해 주세요."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@에 대한 제공업체를 찾지 못했습니다."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "이메일이 일치하지 않습니다."; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "비밀번호 복구"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "비밀번호 재설정 방법을 안내하는 이메일을 보내 드립니다."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "이메일 확인"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "%@(으)로 발송된 이메일의 안내에 따라 비밀번호를 복구하세요."; + +/* Title for sign up screen. */ +"SignUpTitle" = "계정 만들기"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "이름 및 성"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "비밀번호 선택"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "서비스 약관"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "개인정보처리방침"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "계속 진행하면 %@ 및 %@에 동의하는 것으로 간주됩니다."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "이미 다른 계정에서 사용 중인 이메일 주소입니다."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "안전한 비밀번호는 6자 이상이어야 하고 문자와 숫자가 조합되어야 합니다."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "IP 주소에서 계정 요청이 너무 많이 발생하고 있습니다. 잠시 후에 다시 시도해 주세요."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "이미 %@을(를) 사용하여 로그인했습니다. 해당 계정의 비밀번호를 입력하세요."; + +/* OK button title. */ +"OK" = "확인"; + +/* Cancel button title. */ +"Cancel" = "취소"; + +/* Back button title. */ +"Back" = "뒤로"; + +/* Next button title. */ +"Next" = "다음"; + +/* Save button title. */ +"Save" = "저장"; + +/* Send button title. */ +"Send" = "보내기"; + +/* Resend button title. */ +"Resend" = "다시 보내기"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "이메일"; + +/* Label next to a password text field. */ +"Password" = "비밀번호"; + +/* Label next to a name text field. */ +"Name" = "이름"; + +/* Alert title Error. */ +"Error" = "오류"; + +/* Alert button title Close. */ +"Close" = "닫기"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "프로필"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "보안"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "연결된 계정"; + +/* Account Settings cell title Name. */ +"AS_Name" = "이름"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "이메일"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "비밀번호 추가"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "비밀번호 변경"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "로그아웃"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "계정 삭제"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "비밀번호 찾기"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "본인 인증"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "계정을 삭제하시겠습니까?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "계정에 연결된 데이터가 모두 삭제되며 삭제를 취소할 수 없습니다. 이 작업을 완료하려면 다시 로그인해야 합니다."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "계정에 연결된 데이터가 모두 삭제되며 삭제를 취소할 수 없습니다. 계정을 삭제하시겠습니까?"; + +/* Text of Delete action button. */ +"Delete" = "삭제"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "계정 삭제"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "이 작업은 취소할 수 없습니다."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "연결 해제"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "연결된 계정"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "계정 연결 해제 확인"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "이 계정으로 더 이상 로그인할 수 없습니다."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "계정 연결 해제"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "계정에 연결된 이메일 주소를 변경하려면 다시 로그인해야 합니다."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "비밀번호를 변경하려면 먼저 현재 비밀번호를 입력해야 합니다."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "이메일 수정"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "이름 수정"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "계정에 비밀번호를 추가하려면 다시 로그인해야 합니다."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "계정의 비밀번호를 변경하려면 다시 로그인해야 합니다."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "비밀번호를 변경하려면 먼저 현재 비밀번호를 입력해야 합니다."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "비밀번호 추가"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "비밀번호 변경"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "이메일"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@(으)로 로그인"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "이름을 입력하세요."; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "이메일 입력"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "비밀번호를 입력하세요."; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "새 비밀번호"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "비밀번호 선택"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "로그인하는 데 문제가 있나요?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "이메일 확인"; + +/* Title of successfully signed in label. */ +"SignedIn" = "로그인 완료"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "이메일을 받는 데 문제가 있나요?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "다음의 일반적인 해결방법을 시도해 보세요. \n - 이메일이 스팸으로 표시되었거나 필터링되었는지 확인합니다.\n - 인터넷 연결을 확인합니다.\n - 이메일을 잘못 입력하지 않았는지 확인합니다.\n - 받은편지함 용량이 다 찼거나 받은편지함 설정과 관련된 문제가 있는 것이 아닌지 확인합니다.\n 위의 단계로 문제가 해결되지 않으면 이메일을 다시 전송하실 수 있습니다. 이 경우 이전 이메일의 링크는 비활성화됩니다."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "추가 안내가 포함된 로그인 이메일이 %@(으)로 전송되었습니다. 이메일을 확인하여 로그인을 완료하세요."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "로그인 이메일 전송됨"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ln.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ln.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..16bbcd32 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ln.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bienvenue"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Se connecter avec une adresse e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Saisissez votre adresse e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Cette adresse e-mail est incorrecte."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ce type de compte n'est pas compatible avec cette application"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Vous avez déjà un compte"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Vous avez déjà utilisé l'adresse e-mail %@. Connectez-vous avec %@ pour continuer."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Se connecter"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Saisissez votre mot de passe"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Vous devez indiquer un mot de passe."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "L'adresse e-mail et le mot de passe saisis ne correspondent pas."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Cette adresse e-mail ne correspond à aucun compte existant."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Cette adresse e-mail correspond à un compte qui a été désactivé."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Vous avez saisi un mot de passe incorrect un trop grand nombre de fois. Veuillez réessayer dans quelques minutes."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Impossible de trouver un fournisseur pour %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Les adresses e-mail ne correspondent pas"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Récupérez votre mot de passe"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Les instructions relatives à la réinitialisation de votre mot de passe seront envoyées à cette adresse e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Consultez votre boîte de réception"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Suivez les instructions envoyées à l'adresse e-mail %@ pour récupérer votre mot de passe."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Créer un compte"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nom et prénom"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Choisissez un mot de passe"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Conditions d'utilisation"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Règles de confidentialité"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "En continuant, vous acceptez les %@ et les %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Cette adresse e-mail est déjà utilisée par un autre compte."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Les mots de passe sécurisés comportent au moins six caractères et une combinaison de chiffres et de lettres."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "De trop nombreuses demandes de compte proviennent de votre adresse IP. Veuillez réessayer dans quelques minutes."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Vous avez déjà utilisé l'adresse e-mail %@ pour vous connecter. Saisissez votre mot de passe pour ce compte."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annuler"; + +/* Back button title. */ +"Back" = "Retour"; + +/* Next button title. */ +"Next" = "Suivant"; + +/* Save button title. */ +"Save" = "Enregistrer"; + +/* Send button title. */ +"Send" = "Envoyer"; + +/* Resend button title. */ +"Resend" = "Renvoyer"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adresse e-mail"; + +/* Label next to a password text field. */ +"Password" = "Mot de passe"; + +/* Label next to a name text field. */ +"Name" = "Nom"; + +/* Alert title Error. */ +"Error" = "Erreur"; + +/* Alert button title Close. */ +"Close" = "Fermer"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sécurité"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Comptes associés"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nom"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adresse e-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Ajouter un mot de passe"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Modifier le mot de passe"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Se déconnecter"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Supprimer le compte"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Mot de passe oublié"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmez qu'il s'agit bien de vous"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Supprimer le compte ?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Vous devrez vous reconnecter pour finaliser cette opération."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Cette action effacera toutes les données associées à votre compte de façon irréversible. Voulez-vous vraiment supprimer votre compte ?"; + +/* Text of Delete action button. */ +"Delete" = "Supprimer"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Supprimer le compte"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Cette action est irréversible"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Dissocier"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Compte associé"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Dissocier le compte ?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Vous ne pourrez plus utiliser votre compte pour vous connecter"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Dissocier le compte"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Pour modifier l'adresse e-mail associée à votre compte, vous devrez vous reconnecter."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Modifier l'adresse e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Modifier le nom"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Vous devrez vous reconnecter pour ajouter un mot de passe à votre compte."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Vous devrez vous reconnecter pour modifier le mot de passe de votre compte."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Pour modifier votre mot de passe, vous devez d'abord saisir votre mot de passe actuel."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Ajouter un mot de passe"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Modifier le mot de passe"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adresse e-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Se connecter avec %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Saisissez votre nom"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Saisissez votre adresse e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Saisissez votre mot de passe"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nouveau mot de passe"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Choisissez un mot de passe"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Vous ne parvenez pas à vous connecter ?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmez votre adresse e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Connecté"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Vous n'avez pas reçu l'e-mail ?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Essayez les solutions courantes suivantes : \n - Vérifiez que l'e-mail n'a pas été filtré ni marqué comme spam.\n - Vérifiez votre connexion Internet.\n - Vérifiez que votre adresse e-mail est correcte.\n - Vérifiez que votre boîte de réception n'est pas pleine et que les paramètres sont correctement définis.\n Si les étapes décrites ci-dessus n'ont pas résolu le problème, vous pouvez renvoyer l'e-mail. Sachez que le lien du premier e-mail sera alors désactivé."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Un e-mail de connexion avec des instructions supplémentaires a été envoyé à %@. Consultez cet e-mail pour vous connecter."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail de connexion envoyé"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lt.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lt.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..0724a9fb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lt.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Sveiki!"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Prisijungti nurodant el. paštą"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Įveskite el. paštą"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Šis el. paštas netinkamas."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ši programa nepalaiko šio paskyros tipo"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Jūs jau turite paskyrą"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Jau panaudojote %@. Jei norite tęsti, prisijunkite per „%@“."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Prisijungti"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Įveskite slaptažodį"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Slaptažodžio laukas negali būti tuščias."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Įvestas slaptažodis neatitinka el. pašto adreso."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Šis el. pašto adresas neatitinka esamos paskyros."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Šis el. pašto adresas yra išjungtos paskyros."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Įvedėte netinkamą slaptažodį per daug kartų. Po kelių minučių bandykite dar kartą."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nepavyko rasti „%@“ teikėjo."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "El. paštai nesutampa"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Atkurti slaptažodį"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Gaukite instrukcijas su nurodymais, kaip pakeisti slaptažodį, šiuo el. paštu."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Patikrinkite el. paštą"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Vadovaudamiesi el. pašto adresu %@ išsiųstais nurodymais atkurkite slaptažodį."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Sukurti paskyrą"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vardas ir pavardė"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Pasirinkite slaptažodį"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Paslaugų teikimo sąlygomis"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privatumo politika"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Tęsdami nurodote, kad sutinkate su %@ ir %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Šis el. paštas jau naudojamas kitoje paskyroje."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Sudėtingą slaptažodį sudaro bent 6 simboliai ir raidžių bei skaičių derinys."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Iš jūsų IP adreso siunčiama per daug paskyros užklausų. Bandykite dar kartą po kelių minučių."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Jūs jau prisijungėte naudodami %@. Įveskite tos paskyros slaptažodį."; + +/* OK button title. */ +"OK" = "Gerai"; + +/* Cancel button title. */ +"Cancel" = "Atšaukti"; + +/* Back button title. */ +"Back" = "Atgal"; + +/* Next button title. */ +"Next" = "Kitas"; + +/* Save button title. */ +"Save" = "Išsaugoti"; + +/* Send button title. */ +"Send" = "Siųsti"; + +/* Resend button title. */ +"Resend" = "Siųsti iš naujo"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "El. paštas"; + +/* Label next to a password text field. */ +"Password" = "Slaptažodis"; + +/* Label next to a name text field. */ +"Name" = "Vardas"; + +/* Alert title Error. */ +"Error" = "Klaida"; + +/* Alert button title Close. */ +"Close" = "Uždaryti"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profilis"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sauga"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Susietos paskyros"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Vardas"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "El. paštas"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Pridėti slaptažodį"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Keisti slaptažodį"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Atsijungti"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Ištrinti paskyrą"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Pamiršote slaptažodį?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Patvirtinkite savo tapatybę"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Ištrinti paskyrą?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Tai atlikus bus ištrinti visi su jūsų paskyra susiję duomenys; šio veiksmo anuliuoti negalima. Norėdami užbaigti šį veiksmą turėsite prisijungti dar kartą."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Tai atlikus bus ištrinti visi su jūsų paskyra susiję duomenys; šio veiksmo anuliuoti negalima. Ar tikrai norite ištrinti paskyrą?"; + +/* Text of Delete action button. */ +"Delete" = "Ištrinti"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Ištrinti paskyrą"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Šio veiksmo anuliuoti negalima"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Atsieti"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Susieta paskyra"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Atsieti paskyrą?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Nebegalėsite prisijungti naudodami savo paskyrą"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Atsieti paskyrą"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Norėdami pakeisti el. pašto adresą, susietą su paskyra, turėsite prisijungti dar kartą."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Norėdami pakeisti slaptažodį, pirmiausia turite įvesti dabartinį."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Redaguoti el. pašto adresą"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Redaguoti pavadinimą"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Norėdami prie paskyros pridėti slaptažodį, turite prisijungti dar kartą."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Norėdami pakeisti paskyros slaptažodį, turite prisijungti dar kartą."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Norėdami pakeisti slaptažodį, pirmiausia turite įvesti dabartinį."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Pridėti slaptažodį"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Keisti slaptažodį"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "El. paštas"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Prisijungti per „%@“"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Įveskite vardą"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Įveskite el. paštą"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Įveskite slaptažodį"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Naujas slaptažodis"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Pasirinkite slaptažodį"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Kyla problemų prisijungiant?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Patvirtinkite el. paštą"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Prisijungta."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Negaunate el. laiškų?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Išbandykite šiuos dažnai kylančių problemų sprendimo būdus: \n – patikrinkite, ar el. laiškas nebuvo pažymėtas kaip šlamštas arba filtruotas;\n – patikrinkite interneto ryšį;\n – patikrinkite, ar nurodėte tikslų el. pašto adresą;\n – patikrinkite, ar gautiesiems skirta saugyklos vieta nepasibaigė arba kitas su gautųjų nustatymais susijusias problemas.\n Jei ankstesni veiksmai nebuvo naudingi, galite iš naujo išsiųsti el. laišką. Atkreipkite dėmesį, kad šiuo veiksmu bus išaktyvinta ankstesniame el. laiške pateikta nuoroda."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Prisijungimo el. laiškas su papildomomis instrukcijomis išsiųstas adresu %@. Patikrinkite el. paštą, kad užbaigtumėte prisijungimą."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Prisijungimo el. laiškas išsiųstas"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lv.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lv.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..98cf5141 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/lv.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Laipni lūdzam!"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Pierakstīties ar e-pasta adresi"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ievadiet e-pastu"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-pasta adrese nav pareiza."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Šī lietotne neatbalsta šāda veida kontu"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Jums jau ir konts"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Jūs jau esat izmantojis e-pasta adresi %@. Pierakstieties ar %@, lai turpinātu."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Pierakstīties"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ievadiet savu paroli"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Paroles lauks nedrīkst būt tukšs."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Ievadītā e-pasta adrese un parole neatbilst."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-pasta adrese neatbilst esošam kontam."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Šī ir atspējota konta e-pasta adrese."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Esat pārāk daudz reižu ievadījis nepareizu paroli. Lūdzu, mēģiniet vēlreiz pēc dažām minūtēm."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nevar atrast %@ nodrošinātāju."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-pasta adreses nesakrīt"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Paroles atgūšana"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Saņemiet uz šo e-pasta adresi nosūtītus norādījumus ar skaidrojumu par to, kā atiestatīt paroli."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Pārbaudiet savu e-pastu"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Izpildiet uz e-pasta adresi %@ nosūtītos norādījumus, lai atgūtu paroli."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Izveidot kontu"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Vārds un uzvārds"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Izvēlieties paroli"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Pakalpojumu sniegšanas noteikumi"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Konfidencialitātes politika"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Turpinot jūs norādāt, ka piekrītat šādiem dokumentiem: %@ un %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Šī e-pasta adrese jau tiek izmantota citam kontam."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Drošām parolēm ir vismaz 6 rakstzīmes, un tajās ir burtu un ciparu kombinācija."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Pārāk daudz kontu pieprasījumu ir nosūtīti no jūsu IP adreses. Pēc dažām minūtēm mēģiniet vēlreiz."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Esat jau izmantojis e-pasta adresi %@, lai pierakstītos. Ievadiet šī konta paroli."; + +/* OK button title. */ +"OK" = "Labi"; + +/* Cancel button title. */ +"Cancel" = "Atcelt"; + +/* Back button title. */ +"Back" = "Atpakaļ"; + +/* Next button title. */ +"Next" = "Tālāk"; + +/* Save button title. */ +"Save" = "Saglabāt"; + +/* Send button title. */ +"Send" = "Sūtīt"; + +/* Resend button title. */ +"Resend" = "Sūtīt vēlreiz"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-pasts"; + +/* Label next to a password text field. */ +"Password" = "Parole"; + +/* Label next to a name text field. */ +"Name" = "Vārds"; + +/* Alert title Error. */ +"Error" = "Kļūda"; + +/* Alert button title Close. */ +"Close" = "Aizvērt"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profils"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Drošība"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Saistītie konti"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Vārds"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-pasts"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Paroles pievienošana"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Paroles maiņa"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Izrakstīšanās"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Konta dzēšana"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Vai aizmirsāt paroli?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verificējiet savu identitāti"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Vai izdzēst kontu?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Veicot šo darbību, tiks dzēsti visi ar kontu saistītie dati, un to nevarēs atsaukt. Lai veiktu šo darbību, ir vēlreiz jāpierakstās"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Veicot šo darbību, tiks dzēsti visi ar kontu saistītie dati, un to nevarēs atsaukt. Vai tiešām vēlaties dzēst šo kontu?"; + +/* Text of Delete action button. */ +"Delete" = "Dzēst"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Konta dzēšana"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Šo darbību nevar atsaukt"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Atsaistīt"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Saistīts konts"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Vai atsaistīt kontu?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Jūs vairs nevarēsit pierakstīties, izmantojot savu kontu"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Konta atsaistīšana"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Lai mainītu ar kontu saistīto e-pasta adresi, būs vēlreiz jāpierakstās."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Lai mainītu paroli, vispirms ir jāievada pašreizējā parole."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-pasta rediģēšana"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Nosaukuma rediģēšana"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Lai pievienotu kontam paroli, būs vēlreiz jāpierakstās."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Lai mainītu konta paroli, būs vēlreiz jāpierakstās."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Lai mainītu paroli, vispirms ir jāievada pašreizējā parole."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Paroles pievienošana"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Paroles maiņa"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-pasts"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Pierakstīties ar %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ievadiet savu vārdu"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ievadiet e-pastu"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ievadiet savu paroli."; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Jauna parole"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Izvēlieties paroli"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Vai jums ir problēmas ar pierakstīšanos?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Apstipriniet e-pasta adresi"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Esat pierakstījies."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Vai jums ir problēmas ar e-pasta ziņojumu saņemšanu?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Izmēģiniet tālāk norādītās tipiskās problēmu novēršanas iespējas. \n - Pārbaudiet, vai e-pasta ziņojums nav atzīmēts kā mēstule vai nav filtrēts.\n - Pārbaudiet interneta savienojumu.\n - Pārbaudiet, vai e-pasta adrese ir pareizi uzrakstīta.\n - Pārbaudiet, vai jūsu iesūtnes krātuve nav beigusies vai nav citu ar iesūtnes iestatījumiem saistītu problēmu.\n Ja iepriekš minētās darbības nepalīdzēja, varat atkārtoti nosūtīt e-pasta ziņojumu. Ņemiet vērā: tiks deaktivizēta saite no iepriekšējā e-pasta ziņojuma."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Pierakstīšanās e-pasta ziņojums ar papildu norādījumiem tika nosūtīts uz e-pasta adresi %@. Pārbaudiet savu e-pastu, lai pabeigtu pierakstīšanos."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Pierakstīšanās e-pasta ziņojums ir nosūtīts"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/mr.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/mr.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..48d9ff2e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/mr.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "स्वागत आहे"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ईमेलने साइन इन करा"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "तुमचा ईमेल टाका"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "तो ईमेल अॅड्रेस चुकीचा आहे."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "अशा प्रकारच्या खात्याला हे अ‍ॅप समर्थन करत नाही"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "तुमचे आधीच एक खाते आहे"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "तुम्ही %@ आधीच वापरले आहे. सुरू ठेवण्यासाठी %@ने साइन इन करा."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "साइन इन करा"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "तुमचा पासवर्ड टाका"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "पासवर्ड रिक्त ठेवता येणार नाही"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "तुम्ही टाकलेला ईमेल आणि पासवर्ड जुळत नाही."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "तो ईमेल अॅड्रेस सध्याच्या खात्याशी जुळत नाही."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "तो ईमेल अॅड्रेस एका बंद करण्यात आलेल्या खात्याचा आहे."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "तुम्ही चुकीचा पासवर्ड बर्‍याचदा वापरला आहे. थोड्या वेळानंतर पुन्हा प्रयत्न करा."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@साठी पुरवठादार मिळाला नाही."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ईमेल जुळत नाहीत"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "पासवर्ड पुन्हा मिळवा"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "तुमचा पासवर्ड रीसेट कसा करावा यासंबंधित या ईमेलवर पाठवलेल्या सूचना मिळवा."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "तुमचा ईमेल तपासा"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "तुमचा पासवर्ड परत मिळवण्यासाठी %@वर पाठवलेल्या सूचनांचे पालन करा."; + +/* Title for sign up screen. */ +"SignUpTitle" = "खाते तयार करा"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "नाव आणि आडनाव"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "पासवर्ड निवडा"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "सेवा अटी"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "गोपनीयता धोरण"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "पुढे सुरू ठेवून, तुम्ही सूचित करता की तुम्ही आमचे %@ आणि %@ स्वीकारता."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "ईमेल अॅड्रेस दुसर्‍या खात्यावर आधीपासून वापरात आहे."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "सशक्त पासवर्डमध्ये किमान 6 वर्ण आणि अंक, अक्षरांचे मिश्रण असते."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "तुमच्या आयपी अ‍ॅड्रेसवरून बर्‍याच खाते विनंत्या येत आहेत. थोड्या वेळात पुन्हा प्रयत्न करा."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "तुम्ही साइन इन करण्यासाठी %@ आधीच वापरला आहे. तुमचा त्या खात्याचा पासवर्ड टाका."; + +/* OK button title. */ +"OK" = "ठीक आहे"; + +/* Cancel button title. */ +"Cancel" = "रद्द करा"; + +/* Back button title. */ +"Back" = "मागील"; + +/* Next button title. */ +"Next" = "पुढील"; + +/* Save button title. */ +"Save" = "सेव्ह करा"; + +/* Send button title. */ +"Send" = "पाठवा"; + +/* Resend button title. */ +"Resend" = "पुन्हा पाठवा"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ईमेल"; + +/* Label next to a password text field. */ +"Password" = "पासवर्ड"; + +/* Label next to a name text field. */ +"Name" = "नाव"; + +/* Alert title Error. */ +"Error" = "एरर"; + +/* Alert button title Close. */ +"Close" = "बंद करा"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "प्रोफाइल"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "सुरक्षितता"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "लिंक केलेली खाती"; + +/* Account Settings cell title Name. */ +"AS_Name" = "नाव"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ईमेल"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "पासवर्ड जोडा"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "पासवर्ड बदला"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "साइन आउट करा"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "खाते डिलीट करा"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "पासवर्ड विसरलात?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "हे तुम्हीच असल्याची पडताळणी करा"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "खाते हटवायचे का?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "हे तुमच्या खात्याशी संबंधित सर्व डेटा मिटवेल, आणि ते पुन्हा आहे तसे करता येणार नाही, ही अ‍ॅक्शन पूर्ण करण्यासाठी तुम्हाला पुन्हा साइन इन करावे लागेल"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "हे तुमच्या खात्याशी संबंधित सर्व डेटा मिटवेल, आणि ते पुन्हा आहे तसे करता येणार नाही. तुम्हाला खरोखर तुमचे खाते डिलीट करायचे आहे का?"; + +/* Text of Delete action button. */ +"Delete" = "डिलीट करा"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "खाते डिलीत करा"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "ही अ‍ॅक्शन आहे तशी केली जाऊ शकत नाही"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "लिंक काढून टाका"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "लिंक केलेले खाते"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "खाते अनलिंक करायचे?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "तुम्ही यापुढे तुमचे खाते वापरून साइन करू शकणार नाही"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "खाते अनलिंक करा"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "तुमच्या खात्याशी संबंधित असलेला ईमेल अॅड्रेस बदलण्यासाठी तुम्ही पुन्हा साइन इन करणे आवश्यक आहे."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "तुमचा पासवर्ड बदलण्यासाठी आधी तुम्हाला तुमचा सध्याचा पासवर्ड टाकावा लागेल."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ईमेल एडिट करा"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "नाव एडिट करा"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "तुमच्या खात्यामध्ये पासवर्ड जोडण्यासाठी तुम्हाला पुन्हा साइन इन करावे लागेल."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "तुमच्या खात्याचा पासवर्ड बदलण्यासाठी तुम्हाला पुन्हा साइन इन करावे लागेल."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "तुमचा पासवर्ड बदलण्यासाठी आधी तुम्हाला तुमचा सध्याचा पासवर्ड टाकावा लागेल."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "पासवर्ड जोडा"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "पासवर्ड बदला"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ईमेल"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ने साइन इन करा"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "तुमचे नाव टाका"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "तुमचा ईमेल टाका"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "तुमचा पासवर्ड टाका"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "नवीन पासवर्ड"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "पासवर्ड निवडा"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "साइन इन करताना समस्या येत आहे का?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ईमेलची खात्री करा"; + +/* Title of successfully signed in label. */ +"SignedIn" = "साइन इन केले!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "ईमेल मिळवण्यात समस्या येत आहे?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "ही सामान्य निराकरणे करून पाहा: \n- ईमेलला स्पॅम किंवा फिल्टर केलेला म्हणून चिन्हाकिंत केला असल्यास तपासा.\n - तुमचे इंटरनेट कनेक्शन तपासा.\n - तुम्ही तुमच्या ईमेलचे चुकीचे शब्दलेखन केले आहे का ते तपासा.\n - तुमच्या इनबॉक्सची जागा संपली आहे का किंवा अन्य इनबॉक्स सेटिंग्ज संबंधित समस्या आहेत का हे तपासा.\n वरील पायर्‍या वापरून उपयोग झाला नसल्यास, तुम्ही ईमेल पुन्हा पाठवू शकता. लक्षात ठेवा की, यामुळे जुन्या ईमेलमधील लिंक निष्क्रिय केली जाईल."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "अतिरिक्त सूचना असलेला साइन इन ईमेल %@ ला पाठवला होता. साइन इन पूर्ण करण्यासाठी तुमचा ईमेल तपासा."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "साइन इन ईमेल पाठवला"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ms.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ms.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..82bac0ba --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ms.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Selamat datang"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Log masuk dengan e-mel"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Masukkan e-mel anda"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Alamat e-mel tersebut tidak betul."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Akaun jenis ini tidak disokong oleh apl ini"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Anda sudah mempunyai akaun"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Anda sudah menggunakan %@. Log masuk dengan %@ untuk teruskan."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Log masuk"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Masukkan kata laluan anda"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Kata laluan tidak boleh kosong."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "E-mel dan kata laluan yang anda masukkan tidak sepadan."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Alamat e-mel tersebut tidak sepadan dengan akaun sedia ada."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Alamat e-mel tersebut digunakan untuk akaun yang sudah dilumpuhkan."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Anda terlalu kerap memasukkan kata laluan yang salah. Cuba lagi dalam masa beberapa minit."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Tidak dapat mencari pembekal untuk %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-mel tidak sepadan"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Pulihkan kata laluan"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Dapatkan arahan pada e-mel ini untuk mengetahui cara menetapkan semula kata laluan anda."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Semak e-mel anda"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Ikut arahan yang dihantar ke %@ untuk memulihkan kata laluan anda."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Buat akaun"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nama pertama & keluarga"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Pilih kata laluan"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Syarat Perkhidmatan"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Dasar Privasi"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Dengan meneruskan, anda menyatakan bahawa anda menerima %@ dan %@ kami."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Alamat e-mel tersebut sudah digunakan oleh akaun lain."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Kata laluan yang kukuh mengandungi sekurang-kurangnya 6 aksara dan gabungan huruf dengan nombor."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Terlalu banyak permintaan akaun daripada alamat IP anda. Cuba lagi dalam masa beberapa minit."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Anda sudah menggunakan %@ untuk log masuk. Masukkan kata laluan anda untuk akaun tersebut."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Batal"; + +/* Back button title. */ +"Back" = "Kembali"; + +/* Next button title. */ +"Next" = "Seterusnya"; + +/* Save button title. */ +"Save" = "Simpan"; + +/* Send button title. */ +"Send" = "Hantar"; + +/* Resend button title. */ +"Resend" = "Hantar semula"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mel"; + +/* Label next to a password text field. */ +"Password" = "Kata Laluan"; + +/* Label next to a name text field. */ +"Name" = "Nama"; + +/* Alert title Error. */ +"Error" = "Ralat"; + +/* Alert button title Close. */ +"Close" = "Tutup"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Keselamatan"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Akaun Terpaut"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nama"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mel"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Tambahkan kata laluan"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Tukar kata laluan"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Log Keluar"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Padamkan Akaun"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Terlupa kata laluan?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Sahkan identiti anda"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Padamkan Akaun?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Tindakan ini akan memadamkan semua data yang dikaitkan dengan akaun anda dan tidak boleh dibuat asal. Anda perlu log masuk sekali lagi untuk melengkapkan tindakan ini."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Tindakan ini akan memadamkan semua data yang dikaitkan dengan akaun anda dan tidak boleh dibuat asal. Adakah anda pasti anda mahu memadamkan akaun anda?"; + +/* Text of Delete action button. */ +"Delete" = "Padam"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Padamkan akaun"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tindakan ini tidak boleh dibuat asal"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Nyahpaut"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Akaun terpaut"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Nyahpaut akaun?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Anda tidak boleh log masuk menggunakan akaun anda lagi"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Nyahpaut akaun"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Untuk menukar alamat e-mel yang dikaitkan dengan akaun anda, log masuk sekali lagi."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Untuk menukar kata laluan anda, masukkan kata laluan semasa terlebih dahulu."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edit e-mel"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edit nama"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Untuk menambahkan kata laluan pada akaun anda, log masuk sekali lagi."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Untuk menukar kata laluan akaun anda, log masuk sekali lagi."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Untuk menukar kata laluan anda, masukkan kata laluan semasa terlebih dahulu."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Tambahkan kata laluan"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Tukar kata laluan"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mel"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Log masuk dengan %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Masukkan nama anda"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Masukkan e-mel anda"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Masukkan kata laluan anda"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Kata laluan baharu"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Pilih kata laluan"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Menghadapi masalah log masuk?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Sahkan E-mel"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Dilog masuk!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Tidak menerima e-mel?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Cuba pembetulan lazim berikut: \n - Pastikan e-mel tidak ditandakan sebagai spam atau ditapis.\n - Semak sambungan Internet anda.\n - Pastikan e-mel anda dieja dengan betul.\n - Pastikan peti masuk anda tidak kehabisan ruang dan tiada isu berkaitan tetapan peti masuk.\n Jika langkah di atas tidak boleh menyelesaikan isu tersebut, anda boleh menghantar semula e-mel. Sila ambil perhatian bahawa tindakan ini akan menyahaktifkan pautan dalam e-mel sebelumnya."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "E-mel log masuk yang mengandungi arahan tambahan telah dihantar ke %@. Semak e-mel anda untuk melengkapkan log masuk."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mel log masuk Dihantar"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nb.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nb.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..662b6f74 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nb.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Velkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Logg på med e-postadresse"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Oppgi e-postadressen din"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-postadressen er ikke riktig."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Denne kontotypen støttes ikke i denne appen"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Du har allerede en konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Du har allerede brukt %@. Logg på med %@ for å fortsette."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Logg på"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Oppgi passordet ditt"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Du må oppgi et passord."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "E-postadressen og passordet du har angitt, samsvarer ikke."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-postadressen samsvarer ikke med en eksisterende konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-postadressen er for en konto som er deaktivert."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Du har angitt feil passord for mange ganger. Prøv igjen om noen minutter."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Finner ikke leverandøren for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-postadressene samsvarer ikke"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Gjenopprett passordet"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Få instruksjoner sendt til denne e-postadressen for hvordan du tilbakestiller passordet ditt."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Sjekk e-posten din"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Følg veiledningen som er sendt til %@, for å gjenopprette passordet ditt."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Opprett en konto"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Fornavn og etternavn"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Velg passord"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "vilkårene"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Personvernregler"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ved å fortsette godtar du %@ og %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-postadressen brukes allerede av en annen konto."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Sterke passord består av minst seks tegn og en blanding av bokstaver og tall."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Det kommer for mange kontoforespørsler fra IP-adressen din. Prøv igjen om noen minutter."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Du har allerede brukt %@ for å logge på. Oppgi passordet ditt for den kontoen."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Avbryt"; + +/* Back button title. */ +"Back" = "Tilbake"; + +/* Next button title. */ +"Next" = "Neste"; + +/* Save button title. */ +"Save" = "Lagre"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Send på nytt"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-post"; + +/* Label next to a password text field. */ +"Password" = "Passord"; + +/* Label next to a name text field. */ +"Name" = "Navn"; + +/* Alert title Error. */ +"Error" = "Feil"; + +/* Alert button title Close. */ +"Close" = "Lukk"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sikkerhet"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Tilknyttede kontoer"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Navn"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-post"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Legg til passord"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Bytt passord"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Logg av"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Slett kontoen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Har du glemt passordet?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Bekreft identiteten din"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Vil du slette kontoen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Alle data som er tilknyttet kontoen din, blir slettet, og handlingen kan ikke angres. Du må logge på igjen for å fullføre denne handlingen"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Alle data som er tilknyttet kontoen din, blir slettet, og handlingen kan ikke angres. Er du sikker på at du vil slette kontoen din?"; + +/* Text of Delete action button. */ +"Delete" = "Slett"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Slett kontoen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Denne handlingen kan ikke angres"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Fjern tilknytningen"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Tilknyttet konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Vil du fjerne tilknytningen til kontoen?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Du kommer ikke lenger til å kunne logge på med kontoen din"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Fjern tilknytningen til kontoen"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Du må logge på igjen for å endre e-postadressen som er knyttet til kontoen din."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "For å endre passordet ditt må du først oppgi det eksisterende passordet."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Endre e-postadressen"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Endre navnet"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Du må logge på igjen for å legge til passordet i kontoen din."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Du må logge på igjen for å endre til passordet for kontoen din."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "For å endre passordet ditt må du først oppgi det eksisterende passordet."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Legg til passord"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Bytt passord"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-post"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Logg på med %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Oppgi navnet ditt"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Oppgi e-postadressen din"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Oppgi passordet ditt"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nytt passord"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Velg passord"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Har du problemer med å logge på?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Bekreft e-postadressen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Pålogget."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Problemer med å motta e-post?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prøv disse vanlige løsningene: \n — Sjekk om e-posten ble merket som søppelpost eller filtrert bort.\n — Sjekk internettilkoblingen din.\n — Kontrollér at du ikke har skrevet e-postadressen din feil.\n — Kontrollér at innboksen din ikke er full, og se etter andre problemer knyttet til innboksinnstillingene.\n — Hvis trinnene ovenfor ikke bidro til å løse problemet, kan du sende e-posten på nytt. Vær oppmerksom på at dette deaktiverer linken i den forrige e-posten."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "En påloggings-e-post med ytterligere instruksjoner er sendt til %@. Sjekk e-posten din for å fullføre påloggingen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Påloggings-e-post er sendt"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nl.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nl.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..873a407d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nl.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Welkom"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Inloggen met e-mailadres"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Voer uw e-mailadres in"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Dit e-mailadres is niet juist."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Dit accounttype wordt niet ondersteund door deze app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "U heeft al een account"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "U heeft %@ al gebruikt. Log in met %@ om verder te gaan."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Inloggen"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Voer uw wachtwoord in"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Wachtwoord mag niet leeg zijn."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Het ingevoerde e-mailadres en wachtwoord komen niet overeen."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Dit e-mailadres komt niet overeen met een bestaand account."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Dit e-mailadres hoort bij een uitgeschakeld account."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "U heeft te vaak een fout wachtwoord ingevoerd. Probeer het over enkele minuten opnieuw."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Kan de provider niet vinden voor %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-mailadressen komen niet overeen"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Wachtwoord herstellen"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Er wordt een e-mail naar dit adres verzonden met instructies om uw wachtwoord te herstellen."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Controleer uw inbox"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Volg de instructies die we naar %@ hebben verzonden om uw wachtwoord te herstellen."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Account maken"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Voor- en achternaam"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Wachtwoord kiezen"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Servicevoorwaarden"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Privacybeleid"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Door verder te gaan, geeft u aan dat u onze %@ en ons %@ accepteert."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Dit e-mailadres wordt al gebruikt door een ander account."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Sterke wachtwoorden bevatten ten minste zes tekens en een combinatie van letters en cijfers."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Er komen te veel accountaanvragen van uw IP-adres. Probeer het over enkele minuten opnieuw."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "U heeft al ingelogd met %@. Voer uw wachtwoord in voor dit account."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Annuleren"; + +/* Back button title. */ +"Back" = "Terug"; + +/* Next button title. */ +"Next" = "Volgende"; + +/* Save button title. */ +"Save" = "Opslaan"; + +/* Send button title. */ +"Send" = "Verzenden"; + +/* Resend button title. */ +"Resend" = "Opnieuw verzenden"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Wachtwoord"; + +/* Label next to a name text field. */ +"Name" = "Naam"; + +/* Alert title Error. */ +"Error" = "Fout"; + +/* Alert button title Close. */ +"Close" = "Sluiten"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profiel"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Beveiliging"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Gelinkte accounts"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Naam"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Wachtwoord toevoegen"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Wachtwoord wijzigen"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Uitloggen"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Account verwijderen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Wachtwoord vergeten?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Bevestig dat u het bent"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Account verwijderen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Alle gegevens die aan uw account zijn gekoppeld, worden gewist. Dit kan niet ongedaan worden gemaakt. U moet opnieuw inloggen om deze actie te voltooien."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Alle gegevens die aan uw account zijn gekoppeld, worden gewist. Dit kan niet ongedaan worden gemaakt. Weet u zeker dat u uw account wilt verwijderen?"; + +/* Text of Delete action button. */ +"Delete" = "Verwijderen"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Account verwijderen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Deze actie kan niet ongedaan worden gemaakt."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Link verwijderen"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Gelinkt account"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Link met account verwijderen?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "U kunt niet meer inloggen met uw account"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Link met account verwijderen"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Als u het e-mailadres wilt wijzigen dat is gekoppeld aan uw account, moet u opnieuw inloggen."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Om uw wachtwoord te veranderen, moet u eerst uw huidige wachtwoord invoeren."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-mailadres bewerken"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Naam bewerken"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Om een wachtwoord toe te voegen aan uw account, moet u opnieuw inloggen."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Om het wachtwoord van uw account te veranderen, moet u opnieuw inloggen."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Om uw wachtwoord te veranderen, moet u eerst uw huidige wachtwoord invoeren."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Wachtwoord toevoegen"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Wachtwoord wijzigen"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Inloggen met %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Voer uw naam in"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Voer uw e-mailadres in"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Voer uw wachtwoord in"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nieuw wachtwoord"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Wachtwoord kiezen"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problemen met inloggen?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-mailadres bevestigen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Ingelogd"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Ontvangt u e-mails niet?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Probeer deze algemene oplossingen: \n - Controleer of de e-mail als spam is gemarkeerd of is weggefilterd.\n - Controleer uw internetverbinding.\n - Controleer of u uw e-mailadres juist heeft gespeld.\n - Controleer of er voldoende ruimte in uw inbox is en of er geen andere problemen met inboxinstellingen zijn.\n Als de bovenstaande stappen geen uitkomst bieden, kunt u de e-mail opnieuw verzenden. Hiermee wordt de link in de eerdere e-mail gedeactiveerd."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Er is een inlogmail met aanvullende instructies verzonden naar %@. Controleer uw inbox om het inlogproces te voltooien."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Inlogmail verzonden"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nn-NO.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nn-NO.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..662b6f74 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/nn-NO.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Velkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Logg på med e-postadresse"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Oppgi e-postadressen din"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-postadressen er ikke riktig."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Denne kontotypen støttes ikke i denne appen"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Du har allerede en konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Du har allerede brukt %@. Logg på med %@ for å fortsette."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Logg på"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Oppgi passordet ditt"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Du må oppgi et passord."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "E-postadressen og passordet du har angitt, samsvarer ikke."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-postadressen samsvarer ikke med en eksisterende konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-postadressen er for en konto som er deaktivert."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Du har angitt feil passord for mange ganger. Prøv igjen om noen minutter."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Finner ikke leverandøren for %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-postadressene samsvarer ikke"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Gjenopprett passordet"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Få instruksjoner sendt til denne e-postadressen for hvordan du tilbakestiller passordet ditt."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Sjekk e-posten din"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Følg veiledningen som er sendt til %@, for å gjenopprette passordet ditt."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Opprett en konto"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Fornavn og etternavn"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Velg passord"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "vilkårene"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Personvernregler"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ved å fortsette godtar du %@ og %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-postadressen brukes allerede av en annen konto."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Sterke passord består av minst seks tegn og en blanding av bokstaver og tall."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Det kommer for mange kontoforespørsler fra IP-adressen din. Prøv igjen om noen minutter."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Du har allerede brukt %@ for å logge på. Oppgi passordet ditt for den kontoen."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Avbryt"; + +/* Back button title. */ +"Back" = "Tilbake"; + +/* Next button title. */ +"Next" = "Neste"; + +/* Save button title. */ +"Save" = "Lagre"; + +/* Send button title. */ +"Send" = "Send"; + +/* Resend button title. */ +"Resend" = "Send på nytt"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-post"; + +/* Label next to a password text field. */ +"Password" = "Passord"; + +/* Label next to a name text field. */ +"Name" = "Navn"; + +/* Alert title Error. */ +"Error" = "Feil"; + +/* Alert button title Close. */ +"Close" = "Lukk"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Sikkerhet"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Tilknyttede kontoer"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Navn"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-post"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Legg til passord"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Bytt passord"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Logg av"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Slett kontoen"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Har du glemt passordet?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Bekreft identiteten din"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Vil du slette kontoen?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Alle data som er tilknyttet kontoen din, blir slettet, og handlingen kan ikke angres. Du må logge på igjen for å fullføre denne handlingen"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Alle data som er tilknyttet kontoen din, blir slettet, og handlingen kan ikke angres. Er du sikker på at du vil slette kontoen din?"; + +/* Text of Delete action button. */ +"Delete" = "Slett"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Slett kontoen"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Denne handlingen kan ikke angres"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Fjern tilknytningen"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Tilknyttet konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Vil du fjerne tilknytningen til kontoen?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Du kommer ikke lenger til å kunne logge på med kontoen din"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Fjern tilknytningen til kontoen"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Du må logge på igjen for å endre e-postadressen som er knyttet til kontoen din."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "For å endre passordet ditt må du først oppgi det eksisterende passordet."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Endre e-postadressen"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Endre navnet"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Du må logge på igjen for å legge til passordet i kontoen din."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Du må logge på igjen for å endre til passordet for kontoen din."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "For å endre passordet ditt må du først oppgi det eksisterende passordet."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Legg til passord"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Bytt passord"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-post"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Logg på med %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Oppgi navnet ditt"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Oppgi e-postadressen din"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Oppgi passordet ditt"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nytt passord"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Velg passord"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Har du problemer med å logge på?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Bekreft e-postadressen"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Pålogget."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Problemer med å motta e-post?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prøv disse vanlige løsningene: \n — Sjekk om e-posten ble merket som søppelpost eller filtrert bort.\n — Sjekk internettilkoblingen din.\n — Kontrollér at du ikke har skrevet e-postadressen din feil.\n — Kontrollér at innboksen din ikke er full, og se etter andre problemer knyttet til innboksinnstillingene.\n — Hvis trinnene ovenfor ikke bidro til å løse problemet, kan du sende e-posten på nytt. Vær oppmerksom på at dette deaktiverer linken i den forrige e-posten."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "En påloggings-e-post med ytterligere instruksjoner er sendt til %@. Sjekk e-posten din for å fullføre påloggingen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Påloggings-e-post er sendt"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pl.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pl.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..be8d11d8 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pl.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Witamy"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Zaloguj się za pomocą e-maila"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Wpisz swój adres e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Nieprawidłowy adres e-mail."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Konto tego typu nie jest obsługiwane przez tę aplikację"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Masz już konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Adres %@ został już przez Ciebie użyty. Aby kontynuować, zaloguj się przez: %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Zaloguj się"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Wpisz hasło"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Pole z hasłem nie może być puste."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Podany przez Ciebie adres e-mail i hasło nie zgadzają się."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Nie istnieje konto, do którego pasuje ten adres e-mail."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "To jest adres e-mail konta, które zostało wyłączone."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Zbyt wiele razy podano niepoprawne hasło. Spróbuj jeszcze raz za kilka minut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ – nie można znaleźć usługi"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Adresy e-mail są niezgodne"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Odzyskiwanie hasła"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Na ten adres e-mail zostaną wysłane instrukcje wyjaśniające, jak zresetować hasło."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Sprawdź pocztę"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Aby odzyskać hasło, wykonaj instrukcje wysłane na adres %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Tworzenie konta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Imię i nazwisko"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Wybierz hasło"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Warunki korzystania z usługi"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Polityka prywatności"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Kontynuując, potwierdzasz, że akceptujesz te dokumenty: %@ i %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Adres e-mail jest już używany przez inne konto."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Silne hasło ma co najmniej 6 znaków i jest kombinacją liter oraz cyfr."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Z tego adresu IP wysłano zbyt wiele próśb o utworzenie konta. Spróbuj jeszcze raz za kilka minut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Adres e-mail %@ był już używany przez Ciebie do logowania. Wpisz hasło tego konta."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Anuluj"; + +/* Back button title. */ +"Back" = "Wstecz"; + +/* Next button title. */ +"Next" = "Dalej"; + +/* Save button title. */ +"Save" = "Zapisz"; + +/* Send button title. */ +"Send" = "Wyślij"; + +/* Resend button title. */ +"Resend" = "Wyślij ponownie"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adres e-mail"; + +/* Label next to a password text field. */ +"Password" = "Hasło"; + +/* Label next to a name text field. */ +"Name" = "Nazwa"; + +/* Alert title Error. */ +"Error" = "Błąd"; + +/* Alert button title Close. */ +"Close" = "Zamknij"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Zabezpieczenia"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Połączone konta"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nazwa"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adres e-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Dodaj hasło"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Zmień hasło"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Wyloguj się"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Usuń konto"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Nie pamiętasz hasła?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Potwierdź, że to Ty"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Usunąć konto?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Spowoduje to nieodwracalne usunięcie wszystkich danych powiązanych z Twoim kontem. Aby zakończyć tę czynność, musisz jeszcze raz się zalogować"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Spowoduje to nieodwracalne usunięcie wszystkich danych powiązanych z Twoim kontem. Czy na pewno chcesz usunąć konto?"; + +/* Text of Delete action button. */ +"Delete" = "Usuń"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Usuwanie konta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tej czynności nie będzie można cofnąć"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Odłącz"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Połączone konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Czy odłączyć konto?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Logowanie za pomocą tego konta będzie niemożliwe"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Odłączanie konta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Aby zmienić adres e-mail powiązany ze swoim kontem, musisz zalogować się jeszcze raz."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Aby zmienić hasło, musisz najpierw wpisać to, którego używasz obecnie."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Edycja adresu e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Edycja nazwy"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Aby dodać hasło do swojego konta, musisz zalogować się jeszcze raz."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Aby zmienić hasło do swojego konta, musisz zalogować się jeszcze raz."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Aby zmienić hasło, musisz najpierw wpisać to, którego używasz obecnie."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Dodawanie hasła"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Zmiana hasła"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adres e-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Zaloguj się przez: %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Wpisz nazwę"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Wpisz adres e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Wpisz hasło"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nowe hasło"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Wybierz hasło"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Masz problem z zalogowaniem się?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potwierdź adres e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Zalogowano"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "E-maile nie dotarły?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Wypróbuj standardowe rozwiązania: \n – Sprawdź, czy e-mail nie został oznaczony jako spam lub objęty którymś z filtrów.\n – Sprawdź połączenie z internetem.\n – Sprawdź, czy adres e-mail jest wpisany poprawnie.\n – Sprawdź, czy nie kończy się miejsce w skrzynce odbiorczej oraz czy nie ma innych problemów z ustawieniami skrzynki.\n Jeżeli wykonanie powyższych czynności nie dało żadnych rezultatów, możesz wysłać e-maila jeszcze raz. Link wysłany w poprzedniej wiadomości przestanie być aktywny."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Na adres %@ wysłaliśmy e-maila umożliwiającego zalogowanie się z dodatkowymi instrukcjami. Sprawdź pocztę, by się zalogować."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail umożliwiający zalogowanie się został wysłany"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-BR.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-BR.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..2bcf9700 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-BR.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bem-vindo"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Fazer login com o e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Digite seu e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Endereço de e-mail incorreto."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Este tipo de conta não é compatível com este app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Você já tem uma conta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Você já usou o e-mail %@. Faça login com o %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Fazer login"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Digite sua senha"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "A senha não pode estar vazia."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "O e-mail e a senha que você digitou não coincidem."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "O endereço de e-mail não corresponde a uma conta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Esse endereço de e-mail é referente a uma conta que foi desativada."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Você digitou a senha incorretamente várias vezes. Tente novamente em alguns minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Não foi possível localizar o provedor para %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Os e-mails não coincidem"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar senha"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Veja como redefinir sua senha nas instruções enviadas para este e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Verifique seu e-mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Siga as instruções enviadas para %@ para recuperar sua senha."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Criar conta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nome e sobrenome"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Escolha a senha"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Termos de Serviço"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de privacidade"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ao continuar, você concorda com nossos %@ e a %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "O endereço de e-mail já está sendo usado em outra conta."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Senhas fortes têm pelo menos 6 caracteres e uma combinação de letras e números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Seu endereço IP está emitindo muitas solicitações de contas. Tente novamente em alguns minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Você já usou %@ para fazer login. Insira sua senha para essa conta."; + +/* OK button title. */ +"OK" = "Ok"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Voltar"; + +/* Next button title. */ +"Next" = "Próxima"; + +/* Save button title. */ +"Save" = "Salvar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Senha"; + +/* Label next to a name text field. */ +"Name" = "Nome"; + +/* Alert title Error. */ +"Error" = "Erro"; + +/* Alert button title Close. */ +"Close" = "Fechar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Segurança"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Contas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nome"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Adicionar senha"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Alterar senha"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sair"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Excluir conta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Esqueceu a senha?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmar sua identidade"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Excluir conta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta ação apagará todos os dados associados à sua conta e não poderá ser desfeita. Faça login novamente para concluir a ação"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta ação apagará todos os dados associados à sua conta e não poderá ser desfeita. Tem certeza que quer excluir sua conta?"; + +/* Text of Delete action button. */ +"Delete" = "Excluir"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Excluir conta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Não é possível desfazer esta ação"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Conta desvinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Desvincular conta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Você não poderá mais fazer login usando sua conta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular conta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para alterar o endereço de e-mail associado à sua conta, faça login novamente."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para alterar sua senha, primeiro insira sua senha atual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nome"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para adicionar uma senha à sua conta, faça login novamente."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para alterar a senha da sua conta, faça login novamente."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para alterar sua senha, primeiro insira sua senha atual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Adicionar senha"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Alterar senha"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Fazer login com o %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Digite seu nome"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Digite seu e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Digite sua senha"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nova senha"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Escolha a senha"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problemas para fazer login?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirme o e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Conectado!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Está com problemas para receber e-mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Tente estas soluções comuns: \n - Verifique se o e-mail foi filtrado ou marcado como spam.\n - Verifique sua conexão com a Internet.\n - Verifique se você digitou seu e-mail corretamente.\n - Verifique se você ainda tem espaço na sua caixa de entrada, além de outros problemas relacionados à configuração.\n Se as etapas acima não funcionarem, tente enviar o e-mail novamente. Observe que isso desativará o link no e-mail antigo."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Um e-mail de login com mais instruções foi enviado para %@. Verifique sua caixa de entrada para concluir o login."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail de login enviado"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-PT.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-PT.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..ea1c3244 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt-PT.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bem-vindo"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Iniciar sessão com o email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Introduza o seu email"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "O endereço de email não está correto."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "O tipo de conta não é suportado por esta aplicação"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Já tem uma conta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Já utilizou %@. Inicie sessão com %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Iniciar sessão"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Introduza a palavra-passe"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "O campo da palavra-passe não pode ficar vazio."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "O email e a palavra-passe introduzidos não coincidem."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "O endereço de email introduzido não corresponde a uma conta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "O endereço de email introduzido corresponde a uma conta que foi desativada."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Introduziu uma palavra-passe incorreta demasiadas vezes. Tente novamente dentro de alguns minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Não é possível encontrar a operadora de %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Os emails não coincidem"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar a palavra-passe"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Utilize este endereço de email para obter instruções que explicam como repor a palavra-passe."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Verifique o seu email"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Siga as instruções enviadas para %@ para recuperar a palavra-passe."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Criar conta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nome próprio e apelido"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Escolha uma palavra-passe"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Termos de Utilização"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de Privacidade"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ao continuar, indica que aceita os %@ e a %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "O endereço de email já está a ser utilizado por outra conta."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Para criar uma palavra-passe forte é necessário utilizar, no mínimo, 6 caracteres e uma combinação de letras e de números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "O seu endereço de IP enviou demasiados pedidos de conta. Tente novamente dentro de alguns minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Já utilizou %@ para iniciar sessão. Introduza a palavra-passe da conta em questão."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Anterior"; + +/* Next button title. */ +"Next" = "Seguinte"; + +/* Save button title. */ +"Save" = "Guardar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Palavra-passe"; + +/* Label next to a name text field. */ +"Name" = "Nome"; + +/* Alert title Error. */ +"Error" = "Erro"; + +/* Alert button title Close. */ +"Close" = "Fechar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Segurança"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Contas associadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nome"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Adicionar palavra-passe"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Alterar palavra-passe"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Terminar sessão"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Eliminar conta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Esqueceu-se da palavra-passe?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Valide a sua identidade"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Pretende eliminar a conta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta ação apaga todos os dados associados à sua conta e não pode ser anulada. Inicie sessão novamente para concluir esta ação"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta ação apaga todos os dados associados à sua conta e não pode ser anulada. Tem a certeza de que pretende eliminar a sua conta?"; + +/* Text of Delete action button. */ +"Delete" = "Eliminar"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Eliminar conta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Não é possível anular esta ação"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desassociar"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Conta associada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Pretende desassociar a conta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Deixará de poder iniciar sessão com a sua conta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desassociar conta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para alterar o endereço de email associado à sua conta, é necessário iniciar sessão novamente."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para alterar a palavra-passe, primeiro tem de introduzir a palavra-passe atual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nome"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para adicionar uma palavra-passe à sua conta, tem de iniciar sessão novamente."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para alterar a palavra-passe da sua conta, tem de iniciar sessão novamente."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para alterar a palavra-passe, primeiro tem de introduzir a palavra-passe atual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Adicionar palavra-passe"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Alterar palavra-passe"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Iniciar sessão com %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Introduza o seu nome"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Introduza o seu email"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Introduza a palavra-passe"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nova palavra-passe"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Escolha uma palavra-passe"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Está com problemas ao iniciar sessão?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirme o email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Com sessão iniciada!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Está com problemas para receber emails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Experimente estas correções comuns: \n – Verifique se o email foi assinalado como spam ou filtrado.\n – Verifique a ligação à Internet.\n – Certifique-se de que não introduziu o email incorretamente.\n – Certifique-se de que a sua caixa de entrada não está a ficar sem espaço disponível nem está com outros problemas relacionados com as definições da caixa de entrada.\n Se os passos acima não resolverem o problema, pode reenviar o email. Tenha em atenção que esta ação desativa o link no email mais antigo."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Enviámos um email de início de sessão com instruções adicionais para %@. Consulte o seu email para concluir o início de sessão."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Email de início de sessão enviado."; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..2bcf9700 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/pt.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bem-vindo"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Fazer login com o e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Digite seu e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Endereço de e-mail incorreto."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Este tipo de conta não é compatível com este app"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Você já tem uma conta"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Você já usou o e-mail %@. Faça login com o %@ para continuar."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Fazer login"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Digite sua senha"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "A senha não pode estar vazia."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "O e-mail e a senha que você digitou não coincidem."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "O endereço de e-mail não corresponde a uma conta existente."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Esse endereço de e-mail é referente a uma conta que foi desativada."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Você digitou a senha incorretamente várias vezes. Tente novamente em alguns minutos."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Não foi possível localizar o provedor para %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Os e-mails não coincidem"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperar senha"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Veja como redefinir sua senha nas instruções enviadas para este e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Verifique seu e-mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Siga as instruções enviadas para %@ para recuperar sua senha."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Criar conta"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Nome e sobrenome"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Escolha a senha"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Termos de Serviço"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Política de privacidade"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ao continuar, você concorda com nossos %@ e a %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "O endereço de e-mail já está sendo usado em outra conta."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Senhas fortes têm pelo menos 6 caracteres e uma combinação de letras e números."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Seu endereço IP está emitindo muitas solicitações de contas. Tente novamente em alguns minutos."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Você já usou %@ para fazer login. Insira sua senha para essa conta."; + +/* OK button title. */ +"OK" = "Ok"; + +/* Cancel button title. */ +"Cancel" = "Cancelar"; + +/* Back button title. */ +"Back" = "Voltar"; + +/* Next button title. */ +"Next" = "Próxima"; + +/* Save button title. */ +"Save" = "Salvar"; + +/* Send button title. */ +"Send" = "Enviar"; + +/* Resend button title. */ +"Resend" = "Reenviar"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Senha"; + +/* Label next to a name text field. */ +"Name" = "Nome"; + +/* Alert title Error. */ +"Error" = "Erro"; + +/* Alert button title Close. */ +"Close" = "Fechar"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Perfil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Segurança"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Contas vinculadas"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nome"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Adicionar senha"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Alterar senha"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Sair"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Excluir conta"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Esqueceu a senha?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmar sua identidade"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Excluir conta?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Esta ação apagará todos os dados associados à sua conta e não poderá ser desfeita. Faça login novamente para concluir a ação"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Esta ação apagará todos os dados associados à sua conta e não poderá ser desfeita. Tem certeza que quer excluir sua conta?"; + +/* Text of Delete action button. */ +"Delete" = "Excluir"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Excluir conta"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Não é possível desfazer esta ação"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Desvincular"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Conta desvinculada"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Desvincular conta?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Você não poderá mais fazer login usando sua conta"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Desvincular conta"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Para alterar o endereço de e-mail associado à sua conta, faça login novamente."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Para alterar sua senha, primeiro insira sua senha atual."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Editar e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Editar nome"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Para adicionar uma senha à sua conta, faça login novamente."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Para alterar a senha da sua conta, faça login novamente."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Para alterar sua senha, primeiro insira sua senha atual."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Adicionar senha"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Alterar senha"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Fazer login com o %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Digite seu nome"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Digite seu e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Digite sua senha"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nova senha"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Escolha a senha"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Problemas para fazer login?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirme o e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Conectado!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Está com problemas para receber e-mails?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Tente estas soluções comuns: \n - Verifique se o e-mail foi filtrado ou marcado como spam.\n - Verifique sua conexão com a Internet.\n - Verifique se você digitou seu e-mail corretamente.\n - Verifique se você ainda tem espaço na sua caixa de entrada, além de outros problemas relacionados à configuração.\n Se as etapas acima não funcionarem, tente enviar o e-mail novamente. Observe que isso desativará o link no e-mail antigo."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Um e-mail de login com mais instruções foi enviado para %@. Verifique sua caixa de entrada para concluir o login."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-mail de login enviado"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ro.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ro.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..efb9e8eb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ro.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Bun venit"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Conectați-vă cu adresa de e-mail"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Introduceți adresa de e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Adresa de e-mail nu este corectă."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Acest tip de cont nu este acceptat de aplicație"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Aveți deja un cont"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ați folosit deja %@. Pentru a continua, conectați-vă cu %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Conectați-vă"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Introduceți parola"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Parola trebuie completată."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Adresa de e-mail și parola pe care le-ați introdus nu se potrivesc."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Adresa de e-mail nu corespunde unui cont existent."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Această adresă de e-mail aparține unui cont dezactivat."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ați introdus de prea multe ori o parolă incorectă. Încercați din nou peste câteva minute."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Furnizorul pentru %@ nu poate fi găsit."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Adresele de e-mail nu sunt identice"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Recuperați parola"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Primiți instrucțiuni pentru resetarea parolei la această adresă de e-mail."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Verificați căsuța de e-mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Urmați instrucțiunile trimise la %@ pentru a vă recupera parola."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Creați un cont"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Prenume și nume de familie"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Alegeți o parolă"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Termeni și condițiile"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Politica de confidențialitate"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Dacă alegeți să continuați, sunteți de acord cu %@ și cu %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Adresa de e-mail este folosită deja de alt cont."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Parolele puternice au cel puțin 6 caractere și conțin o combinație de litere și cifre."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Au fost create prea multe solicitări de conturi de la această adresă IP. Încercați din nou peste câteva minute."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ați folosit deja %@ pentru a vă conecta. Introduceți parola acestui cont."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Anulați"; + +/* Back button title. */ +"Back" = "Înapoi"; + +/* Next button title. */ +"Next" = "Înainte"; + +/* Save button title. */ +"Save" = "Salvați"; + +/* Send button title. */ +"Send" = "Trimiteți"; + +/* Resend button title. */ +"Resend" = "Retrimiteți"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Adresă de e-mail"; + +/* Label next to a password text field. */ +"Password" = "Parolă"; + +/* Label next to a name text field. */ +"Name" = "Nume"; + +/* Alert title Error. */ +"Error" = "Eroare"; + +/* Alert button title Close. */ +"Close" = "Închideți"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Securitate"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Conturi conectate"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Nume"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Adresă de e-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Adăugați parola"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Schimbați parola"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Deconectați-vă"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Ștergeți contul"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Ați uitat parola?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Confirmați-vă identitatea"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Ștergeți contul?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Toate datele asociate acestui cont vor fi șterse, iar acțiunea nu poate fi anulată. Va trebui să vă conectați din nou pentru a finaliza acțiunea."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Toate datele asociate acestui cont vor fi șterse, iar acțiunea nu poate fi anulată. Sigur doriți să vă ștergeți contul?"; + +/* Text of Delete action button. */ +"Delete" = "Ștergeți"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Ștergeți contul"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Această acțiune nu poate fi anulată"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Deconectați"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Cont conectat"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Deconectați contul?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Nu vă veți mai putea conecta folosind contul"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Deconectați contul"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Pentru a schimba adresa de e-mail asociată contului, va trebui să vă conectați din nou."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Pentru a vă schimba parola, trebuie să introduceți parola actuală."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Modificați adresa de e-mail"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Modificați numele"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Pentru a adăuga parola contului, va trebui să vă conectați din nou."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Pentru a schimba parola contului, va trebui să vă conectați din nou."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Pentru a vă schimba parola, trebuie să introduceți parola actuală."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Adăugați parola"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Schimbați parola"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Adresă de e-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Conectați-vă cu %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Introduceți numele"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Introduceți adresa de e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Introduceți parola"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Parolă nouă"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Alegeți o parolă"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Nu reușiți să vă conectați?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Confirmați adresa de e-mail"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Conectat(ă)!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Nu primiți e-mailuri?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Încercați aceste soluții frecvent folosite: \n - verificați dacă e-mailul a fost marcat ca spam sau filtrat;\n - verificați conexiunea la internet;\n - verificați dacă ați scris corect adresa de e-mail;\n - verificați dacă aveți spațiu în căsuța de e-mail sau dacă există alte probleme legate de setările căsuței de e-mail.\n Dacă pașii de mai sus nu funcționează, puteți să trimiteți din nou e-mailul. Rețineți că va fi dezactivat linkul din e-mailul anterior."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Un e-mail de conectare cu instrucțiuni suplimentare a fost trimis la %@. Verificați-vă căsuța de e-mail pentru a finaliza conectarea."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "A fost trimis e-mailul de conectare"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ru.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ru.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..5a85070c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ru.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Добро пожаловать!"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Войти по адресу электронной почты"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Введите свой адрес электронной почты"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Неверный адрес электронной почты."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "В этом приложении не поддерживается такой тип аккаунта."; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "У вас уже есть аккаунт"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Вы уже использовали адрес %@. Войдите через аккаунт %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Войти"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Введите пароль"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Укажите пароль."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Неверный адрес эл. почты или пароль."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Нет аккаунта с таким адресом электронной почты."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Аккаунт с этим адресом электронной почты отключен."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Вы неправильно ввели пароль слишком много раз. Прежде чем повторить попытку, подождите несколько минут."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@: поставщик услуг не найден."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Адреса электронной почты не совпадают."; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Сбор пароля"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "На этот адрес будет отправлено письмо с инструкциями по сбросу пароля."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Проверьте электронную почту"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "На адрес %@ отправлено письмо с инструкциями по сбросу пароля."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Создать аккаунт"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Имя и фамилия"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Выберите пароль"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Условия использования"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Политика конфиденциальности"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Продолжая, вы принимаете два документа. Вот они: %@ и %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Этот адрес электронной почты уже используется в другом аккаунте."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Пароль должен состоять из букв и цифр и содержать не меньше шести символов."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "С вашего IP-адреса поступает слишком много запросов на создание аккаунта. Повторите попытку через несколько минут."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Вы уже использовали адрес %@. Введите пароль для этого аккаунта."; + +/* OK button title. */ +"OK" = "ОК"; + +/* Cancel button title. */ +"Cancel" = "Отмена"; + +/* Back button title. */ +"Back" = "Назад"; + +/* Next button title. */ +"Next" = "Далее"; + +/* Save button title. */ +"Save" = "Сохранить"; + +/* Send button title. */ +"Send" = "Отправить"; + +/* Resend button title. */ +"Resend" = "Отправить ещё раз"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Адрес электронной почты"; + +/* Label next to a password text field. */ +"Password" = "Пароль"; + +/* Label next to a name text field. */ +"Name" = "Имя"; + +/* Alert title Error. */ +"Error" = "Ошибка"; + +/* Alert button title Close. */ +"Close" = "Закрыть"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Профиль"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Безопасность"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Связанные аккаунты"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Имя"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Адрес электронной почты"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Добавить пароль"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Изменить пароль"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Выйти"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Удалить аккаунт"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Забыли пароль?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Подтвердите, что это вы"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Удалить аккаунт?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Все данные в нем будут безвозвратно удалены. Чтобы завершить это действие, нужно будет войти в аккаунт ещё раз."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Все данные в аккаунте будут безвозвратно удалены. Вы уверены, что хотите продолжить?"; + +/* Text of Delete action button. */ +"Delete" = "Удалить"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Удаление аккаунта"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Отменить это действие невозможно."; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Отменить связь"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Связанный аккаунт"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Отменить связь с аккаунтом?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Вы больше не сможете входить в систему с его помощью."; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Отменить связь с аккаунтом"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Чтобы связать с аккаунтом другой адрес, потребуется повторно войти в систему."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Сначала нужно ввести текущий пароль."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Изменить адрес электронной почты"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Изменить имя"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Чтобы добавить новый пароль, нужно будет войти в аккаунт ещё раз."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Чтобы изменить пароль, нужно будет войти в аккаунт ещё раз."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Сначала нужно ввести текущий пароль."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Добавить пароль"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Изменить пароль"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Адрес электронной почты"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Войти через аккаунт %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Введите свое имя"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Введите свой адрес электронной почты"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Введите пароль"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Новый пароль"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Выберите пароль"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Не удается войти в аккаунт?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Подтвердите адрес электронной почты"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Вход выполнен"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Не получили письмо?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Вот что можно сделать: \n – Поищите письмо в папке со спамом или отфильтрованными сообщениями.\n – Проверьте подключение к Интернету.\n – Убедитесь, что правильно указали свой адрес электронной почты.\n – Проверьте настройки папки со входящими сообщениям и посмотрите, достаточно ли в ней места.\n Если найти письмо не удалось, мы можем отправить его ещё раз. В таком случае ссылка из предыдущего сообщения станет недействительна."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "На адрес электронной почты %@ отправлено письмо с информацией о том, как войти в аккаунт. Изучите его и выполните инструкции."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Письмо отправлено."; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sk.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sk.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..da3c9cc1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sk.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Vitajte"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Prihlásiť sa e-mailom"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Zadajte svoj e-mail"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Daná e-mailová adresa nie je správna."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Táto aplikácia nepodporuje tento typ účtu"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Už máte účet"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Už ste použili adresu %@. Ak chcete pokračovať, prihláste sa cez %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Prihlásiť sa"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Zadajte svoje heslo"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Heslo nesmie byť prázdne."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Zadaný e-mail a heslo sa nezhodujú."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Daná e-mailová adresa sa nezhoduje s existujúcim účtom."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Daná e-mailová adresa patrí k účtu, ktorý bol deaktivovaný."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Zadali ste nesprávne heslo príliš veľakrát. Skúste to znova o pár minút."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nemožno nájsť poskytovateľa pre službu %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-maily sa nezhodujú"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Obnovenie hesla"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Nechajte si na tento e-mail poslať pokyny s vysvetlením, ako obnoviť svoje heslo."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Skontrolujte si e-mail"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Obnovte si heslo podľa pokynov odoslaných na adresu %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Vytvoriť účet"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Krstné meno a priezvisko"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Zvoľte si heslo"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Zmluvné podmienky"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Pravidlá ochrany súkromia"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Pokračovaním vyjadrujete súhlas s dokumentmi %@ a %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-mailovú adresu už využíva iný účet."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Silné heslá majú aspoň 6 znakov a kombinujú písmena a čísla."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Z vašej adresy IP prichádza príliš veľa žiadostí o účet. Skúste to znova o pár minút."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Na prihlásenie ste už použili e-mailovú adresu %@. Zadajte heslo pre daný účet."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Zrušiť"; + +/* Back button title. */ +"Back" = "Späť"; + +/* Next button title. */ +"Next" = "Ďalej"; + +/* Save button title. */ +"Save" = "Uložiť"; + +/* Send button title. */ +"Send" = "Odoslať"; + +/* Resend button title. */ +"Resend" = "Odoslať znova"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-mail"; + +/* Label next to a password text field. */ +"Password" = "Heslo"; + +/* Label next to a name text field. */ +"Name" = "Názov"; + +/* Alert title Error. */ +"Error" = "Chyba"; + +/* Alert button title Close. */ +"Close" = "Zatvoriť"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Zabezpečenie"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Prepojené účty"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Názov"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-mail"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Pridanie hesla"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Zmena hesla"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Odhlásenie"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Odstránenie účtu"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Zabudli ste heslo?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Overte, že ste to vy"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Chcete odstrániť účet?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Týmto sa vymažú všetky dáta súvisiace s vaším účtom a túto akciu nie je možné vrátiť späť. Na dokončenie tejto akcie sa budete musieť prihlásiť"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Týmto sa vymažú všetky dáta súvisiace s vaším účtom a túto akciu nie je možné vrátiť späť. Naozaj chcete odstrániť svoj účet?"; + +/* Text of Delete action button. */ +"Delete" = "Odstrániť"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Odstrániť účet"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Túto akciu nie je možné vrátiť späť"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Odpojiť"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Prepojený účet"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Chcete odpojiť účet?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Už sa nebudete môcť prihlásiť svojím účtom"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Odpojiť účet"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Ak chcete zmeniť e-mailovú adresu prepojenú s vaším účtom, budete sa musieť znova prihlásiť."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Ak chcete zmeniť heslo, musíte najskôr zadať aktuálne heslo."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Úprava e-mailu"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Úprava názvu"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Ak chcete k účtu pridať heslo, budete sa musieť znova prihlásiť."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Ak chcete zmeniť heslo svojho účtu, budete sa musieť znova prihlásiť."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Ak chcete zmeniť heslo, musíte najskôr zadať aktuálne heslo."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Pridanie hesla"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Zmena hesla"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-mail"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Prihlásiť sa cez %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Zadajte svoje meno"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Zadajte svoj e-mail"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Zadajte svoje heslo"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nové heslo"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Zvoľte si heslo"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Máte problémy s prihlásením?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potvrdenie e‑mailovej adresy"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Prihlásili ste sa."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Máte problémy s prijímaním e‑mailov?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Vyskúšajte tieto bežné riešenia: \n – Skontrolujte, či bol e‑mail označený ako spam alebo či bol odfiltrovaný.\n – Skontrolujte internetové pripojenie.\n – Skontrolujte, či ste správne napísali svoju e‑mailovú adresu.\n – Skontrolujte, či máte v doručenej pošte dostatok miesta alebo či nemáte iné problémy súvisiace s nastaveniami doručenej pošty.\n Ak kroky uvedené vyššie nepomohli, môžete si e‑mail nechať poslať znova. Upozorňujeme, že sa tým deaktivuje odkaz v staršom e‑maile."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Prihlasovací e‑mail s ďalšími pokynmi bol odoslaný na adresu %@. Pozrite si poštu a dokončite prihlásenie."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Prihlasovací e‑mail bol odoslaný"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sl.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sl.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..5509a558 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sl.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Dobrodošli"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Prijava z e-pošto"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Vnesite e-pošto"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-pošta ni pravilna."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Aplikacija ne podpira te vrste računov"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Račun že imate"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "E-poštni naslov %@ ste že uporabili. Če želite nadaljevati, se prijavite z računom za %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Prijava"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Vnesite geslo"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Geslo ne sme biti prazno."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "E-poštni naslov in geslo, ki ste ju vnesli, se ne ujemata."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-poštni naslov se ne ujema z obstoječim računom."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-poštni naslov je za račun, ki je bil onemogočen."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Prevečkrat ste vnesli nepravilno geslo. Poskusite znova čez nekaj minut."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Ponudnika za %@ ni mogoče najti."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-pošti se ne ujemata"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Obnovitev gesla"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Na to e-pošto vam bomo poslali navodila za ponastavitev gesla."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Preverite e-pošto"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Če želite obnoviti geslo, upoštevajte navodila, ki smo jih poslali na naslov %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Ustvarjanje računa"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Ime in priimek"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Izberite geslo"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "pogoji storitve"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Pravilnik o zasebnosti"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Z nadaljevanjem potrjujete, da se strinjate z dokumentoma %@ in %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-poštni naslov že uporablja drug račun."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Zapletena gesla imajo vsaj 6 znakov in so sestavljena iz kombinacije črk ter številk"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Z vašega naslova IP prihaja preveč zahtev za ustvarjanje novih računov. Poskusite znova čez nekaj minut."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "E-poštni naslov %@ ste že uporabili za prijavo. Vnesite geslo za ta račun."; + +/* OK button title. */ +"OK" = "V redu"; + +/* Cancel button title. */ +"Cancel" = "Prekliči"; + +/* Back button title. */ +"Back" = "Nazaj"; + +/* Next button title. */ +"Next" = "Naprej"; + +/* Save button title. */ +"Save" = "Shrani"; + +/* Send button title. */ +"Send" = "Pošlji"; + +/* Resend button title. */ +"Resend" = "Pošlji znova"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-pošta"; + +/* Label next to a password text field. */ +"Password" = "Geslo"; + +/* Label next to a name text field. */ +"Name" = "Ime"; + +/* Alert title Error. */ +"Error" = "Napaka"; + +/* Alert button title Close. */ +"Close" = "Zapri"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Varnost"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Povezani računi"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Ime"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-pošta"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Dodajanje gesla"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Spreminjanje gesla"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Odjava"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Brisanje računa"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Ali ste pozabili geslo?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Potrdite, da ste to vi"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Ali želite izbrisati račun?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "S tem dejanjem, ki ga ni mogoče razveljaviti, boste izbrisali vse podatke, povezane z vašim računom. Če želite dokončati to dejanje, se boste morali prijaviti znova."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "S tem dejanjem, ki ga ni mogoče razveljaviti, boste izbrisali vse podatke, povezane z vašim računom. Ali ste prepričani, da želite izbrisati svoj račun?"; + +/* Text of Delete action button. */ +"Delete" = "Izbriši"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Brisanje računa"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Tega dejanja ni mogoče razveljaviti"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Prekini povezavo"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Povezan račun"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Ali želite prekiniti povezavo z računom?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "S svojim računom se ne boste mogli več prijaviti"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Prekini povezavo z računom"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Če želite spremeniti e-poštni naslov, povezan z vašim računom, se boste morali prijaviti znova."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Če želite spremeniti geslo, morate najprej vnesti trenutno geslo."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Urejanje e-pošte"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Urejanje imena"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Če želite računu dodati geslo, se boste morali prijaviti znova."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Če želite spremeniti geslo računa, se boste morali prijaviti znova."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Če želite spremeniti geslo, morate najprej vnesti trenutno geslo."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Dodajanje gesla"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Spreminjanje gesla"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-pošta"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Prijava z računom za %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Vnesite ime"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Vnesite e-pošto"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Vnesite geslo"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Novo geslo"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Izberite geslo"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Ali imate težave pri prijavi?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potrditev e-poštnega naslova"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Prijavljeni ste."; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Niste prejeli e-poštnega sporočila?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Poskusite te splošne rešitve: \n – Preverite, ali je bilo e-poštno sporočilo označeno kot vsiljena pošta ali filtrirano.\n – Preverite internetno povezavo.\n – Preverite, ali je e-poštni naslov pravilno zapisan.\n – Zagotovite, da imate v nabiralniku dovolj prostora oziroma da ni prišlo do drugih težav, povezanih z nastavitvami nabiralnika.\n – Če z zgornjimi koraki ne odpravite težave, lahko znova pošljete e-poštno sporočilo. Upoštevajte, da boste s tem onemogočili povezavo v prejšnjem e-poštnem sporočilu."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "E-poštno sporočilo za prijavo z dodatnimi navodili je bilo poslano na %@. Preverite e-pošto in dokončajte prijavo."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "E-poštno sporočilo za prijavo je bilo poslano"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr-Latn.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr-Latn.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..fd9a4ecf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr-Latn.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Dobro došli"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Prijavi me pomoću imejla"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Unesite imejl"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Ta imejl adresa nije tačna."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ova aplikacija ne podržava taj tip naloga"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Već imate nalog"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Već ste upotrebili %@. Prijavite se pomoću %@-a da biste nastavili."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Prijavi me"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Unesite lozinku"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Lozinka mora da se unese."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Imejl i lozinka koje ste uneli se ne podudaraju."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Ta imejl adresa ne odgovara nijednom postojećem nalogu."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Ta imejl adresa pripada deaktiviranom nalogu."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Previše puta ste uneli netačnu lozinku. Probajte ponovo za par minuta."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Nismo uspeli da nađemo dobavljača za %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Imejlovi se ne podudaraju"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Povratite lozinku"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Na ovaj imejl ćete dobiti uputstva kako da resetujete lozinku."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Proverite imejl"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Pratite uputstva koja smo vam poslali na %@ da biste povratili lozinku."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Otvorite nalog"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Ime i prezime"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Izaberite lozinku"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Uslovi korišćenja usluge"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Politika privatnosti"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ako nastavite, potvrđujete da prihvatate dokumente %@ i %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ova imejl adresa se već koristi za drugi nalog."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Jake lozinke imaju bar 6 znakova, uz kombinaciju slova i brojeva."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Sa vaše IP adrese potiče previše zahteva za nalog. Probajte ponovo za par minuta."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Već ste koristili adresu %@ za prijavljivanje. Unesite lozinku za taj nalog."; + +/* OK button title. */ +"OK" = "Potvrdi"; + +/* Cancel button title. */ +"Cancel" = "Otkaži"; + +/* Back button title. */ +"Back" = "Nazad"; + +/* Next button title. */ +"Next" = "Sledeće"; + +/* Save button title. */ +"Save" = "Sačuvaj"; + +/* Send button title. */ +"Send" = "Pošalji"; + +/* Resend button title. */ +"Resend" = "Ponovo pošalji"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Imejl"; + +/* Label next to a password text field. */ +"Password" = "Lozinka"; + +/* Label next to a name text field. */ +"Name" = "Ime"; + +/* Alert title Error. */ +"Error" = "Greška"; + +/* Alert button title Close. */ +"Close" = "Zatvori"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Bezbednost"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Povezani nalozi"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Ime"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Imejl"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Dodajte lozinku"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Promenite lozinku"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Odjavi me"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Brisanje naloga"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Zaboravili ste lozinku?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Potvrdite da ste to vi"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Želite li da izbrišete nalog?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Ovim ćete trajno izbrisati sve podatke povezane sa nalogom. Treba da se ponovo prijavite da biste mogli da obavite ovu radnju"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Ovim ćete trajno izbrisati sve podatke povezane sa nalogom. Želite li stvarno da izbrišete nalog?"; + +/* Text of Delete action button. */ +"Delete" = "Izbriši"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Izbriši nalog"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Ova radnja ne može da se opozove"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Opozovi vezu"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Povezani nalog"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Želite li da opozovete vezu sa nalogom?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Više nećete moći da se prijavljujete pomoću naloga"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Opoziv veze sa nalogom"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Da biste promenili imejl adresu povezanu sa nalogom, treba da se ponovo prijavite."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Da biste promenili lozinku, treba da unesete trenutnu lozinku."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Izmena imejla"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Izmena naziva"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Da biste nalogu dodali lozinku, treba ponovo da se prijavite."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Da biste promenili lozinku naloga, treba ponovo da se prijavite."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Da biste promenili lozinku, treba je da unesete trenutnu lozinku."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Dodajte lozinku"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Promenite lozinku"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Imejl"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Prijavite se pomoću %@-a"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Unesite ime"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Unesite imejl"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Unesite lozinku"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nova lozinka"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Izaberite lozinku"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Imate problema pri prijavljivanju?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Potvrdite imejl adresu"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Prijavljeni ste!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Imate problema sa prijemom imejla?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Probajte ova uobičajena rešenja: \n– Proverite da li je imejl filtriran ili obeležen kao nepoželjan.\n – Proverite internet vezu.\n – Proverite da li ste tačno upisali imejl adresu.\n – Proverite da niste ostali bez prostora u prijemnom sandučetu, odnosno da nema drugih problema sa prijemnim sandučetom.\n Ako navedene mere ne urode plodom, možete ponovo da pošaljete imejl. Imajte u vidu da ćete time deaktivirati link u starijem imejlu."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Imejl za prijavljivanje sa dodatnim uputstvima je poslat na %@. Proverite imejl da biste dovršili prijavljivanje."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Poslali smo vam imejl za prijavljivanje"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..34f17afb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sr.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Добро дошли"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Пријави ме помоћу имејла"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Унесите имејл"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Та имејл адреса није тачна."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Ова апликација не подржава тај тип налога"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Већ имате налог"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Већ сте употребили %@. Пријавите се помоћу %@-а да бисте наставили."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Пријави ме"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Унесите лозинку"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Лозинка мора да се унесе."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Имејл и лозинка које сте унели се не подударају."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Та имејл адреса не одговара ниједном постојећем налогу."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Та имејл адреса припада деактивираном налогу."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Превише пута сте унели нетачну лозинку. Пробајте поново за пар минута."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Нисмо успели да нађемо добављача за %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Имејлови се не подударају"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Повратите лозинку"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "На овај имејл ћете добити упутства како да ресетујете лозинку."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Проверите имејл"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Пратите упутства која смо вам послали на %@ да бисте повратили лозинку."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Отворите налог"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Име и презиме"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Изаберите лозинку"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Услови коришћења услуге"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Политика приватности"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Ако наставите, потврђујете да прихватате документе %@ и %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ова имејл адреса се већ користи за други налог."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Јаке лозинке имају бар 6 знакова, уз комбинацију слова и бројева."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Са ваше IP адресе потиче превише захтева за налог. Пробајте поново за пар минута."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Већ сте користили адресу %@ за пријављивање. Унесите лозинку за тај налог."; + +/* OK button title. */ +"OK" = "Потврди"; + +/* Cancel button title. */ +"Cancel" = "Откажи"; + +/* Back button title. */ +"Back" = "Назад"; + +/* Next button title. */ +"Next" = "Следеће"; + +/* Save button title. */ +"Save" = "Сачувај"; + +/* Send button title. */ +"Send" = "Пошаљи"; + +/* Resend button title. */ +"Resend" = "Поново пошаљи"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Имејл"; + +/* Label next to a password text field. */ +"Password" = "Лозинка"; + +/* Label next to a name text field. */ +"Name" = "Име"; + +/* Alert title Error. */ +"Error" = "Грешка"; + +/* Alert button title Close. */ +"Close" = "Затвори"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Профил"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Безбедност"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Повезани налози"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Име"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Имејл"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Додајте лозинку"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Промените лозинку"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Одјави ме"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Брисање налога"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Заборавили сте лозинку?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Потврдите да сте то ви"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Желите ли да избришете налог?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Овим ћете трајно избрисати све податке повезане са налогом. Треба да се поново пријавите да бисте могли да обавите ову радњу"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Овим ћете трајно избрисати све податке повезане са налогом. Желите ли стварно да избришете налог?"; + +/* Text of Delete action button. */ +"Delete" = "Избриши"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Избриши налог"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Ова радња не може да се опозове"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Опозови везу"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Повезани налог"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Желите ли да опозовете везу са налогом?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Више нећете моћи да се пријављујете помоћу налога"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Опозив везе са налогом"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Да бисте променили имејл адресу повезану са налогом, треба да се поново пријавите."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Да бисте променили лозинку, треба да унесете тренутну лозинку."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Измена имејла"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Измена назива"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Да бисте налогу додали лозинку, треба поново да се пријавите."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Да бисте променили лозинку налога, треба поново да се пријавите."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Да бисте променили лозинку, треба је да унесете тренутну лозинку."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Додајте лозинку"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Промените лозинку"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Имејл"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Пријавите се помоћу %@-а"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Унесите име"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Унесите имејл"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Унесите лозинку"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Нова лозинка"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Изаберите лозинку"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Имате проблема при пријављивању?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Потврдите имејл адресу"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Пријављени сте!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Имате проблема са пријемом имејла?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Пробајте ова уобичајена решења: \n– Проверите да ли је имејл филтриран или обележен као непожељан.\n – Проверите интернет везу.\n – Проверите да ли сте тачно уписали имејл адресу.\n – Проверите да нисте остали без простора у пријемном сандучету, односно да нема других проблема са пријемним сандучетом.\n Ако наведене мере не уроде плодом, можете поново да пошаљете имејл. Имајте у виду да ћете тиме деактивирати линк у старијем имејлу."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Имејл за пријављивање са додатним упутствима је послат на %@. Проверите имејл да бисте довршили пријављивање."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Послали смо вам имејл за пријављивање"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sv.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sv.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..e7c94ec5 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/sv.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Välkommen"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Logga in med e-post"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Ange din e-postadress"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "E-postadressen är ogiltig."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Appen stöder inte den här typen av konto"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Du har redan ett konto"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Du har redan använt %@. Logga in med %@ om du vill fortsätta."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Logga in"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Ange ditt lösenord"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Du måste ange lösenord."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "E-postadressen och lösenordet matchar inte."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "E-postadressen matchar inget befintligt konto."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "E-postadressen tillhör ett inaktiverat konto."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Du har angett fel lösenord för många gånger. Försök igen om några minuter."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Det gick inte att hitta någon leverantör för %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-postadresserna stämmer inte överens"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Återställa lösenord"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Få ett e-postmeddelande med anvisningar för hur du återställer lösenordet."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Kolla dina e-postmeddelanden"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Följ anvisningarna som har skickats till %@ för att återställa ditt lösenord."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Skapa konto"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "För- och efternamn"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Välj lösenord"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Användarvillkor"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Sekretesspolicy"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Genom att fortsätta godkänner du våra %@ och vår %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-postadressen används redan av ett annat konto."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Starka lösenord består av minst 6 tecken och en blandning av bokstäver och siffror."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Det kommer för många kontobegäranden från din IP-adress. Försök igen om några minuter."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Du har redan loggat in med %@. Ange lösenordet för det kontot."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Avbryt"; + +/* Back button title. */ +"Back" = "Föregående"; + +/* Next button title. */ +"Next" = "Nästa"; + +/* Save button title. */ +"Save" = "Spara"; + +/* Send button title. */ +"Send" = "Skicka"; + +/* Resend button title. */ +"Resend" = "Skicka igen"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-post"; + +/* Label next to a password text field. */ +"Password" = "Lösenord"; + +/* Label next to a name text field. */ +"Name" = "Namn"; + +/* Alert title Error. */ +"Error" = "Fel"; + +/* Alert button title Close. */ +"Close" = "Stäng"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Säkerhet"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Länkade konton"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Namn"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-post"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Lägg till lösenord"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Ändra lösenord"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Logga ut"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Radera konto"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Har du glömt lösenordet?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Verifiera dig"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Radera konto?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "All data som är kopplad till ditt konto raderas permanent. Du måste logga in igen för att slutföra åtgärden."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "All data som är kopplad till ditt konto raderas permanent. Är du säker på att du vill radera kontot?"; + +/* Text of Delete action button. */ +"Delete" = "Radera"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Radera konto"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Det går inte att ångra åtgärden"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Ta bort länk"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Länkat konto"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Ta bort länk till konto?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Du kommer inte längre att kunna logga in med kontot"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Ta bort länk till konto"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Du måste logga in igen om du vill ändra vilken e-postadress som är länkad till ditt konto."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Du måste först ange ditt aktuella lösenord för att kunna ändra lösenordet."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Redigera e-postadress"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Redigera namn"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Du måste logga in igen för att kunna lägga till lösenord för kontot."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Du måste logga in igen för att kunna ändra lösenord för kontot."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Du måste först ange ditt aktuella lösenord för att kunna ändra lösenordet."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Lägg till lösenord"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Ändra lösenord"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-post"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Logga in med %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Ange ditt namn"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Ange din e-postadress"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Ange ditt lösenord"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Nytt lösenord"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Välj lösenord"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Har du problem med att logga in?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Bekräfta e-post"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Inloggad!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Får du inte e-postmeddelanden?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Prova dessa vanliga lösningar: \n – Kontrollera om meddelandet hamnade bland skräpposten eller filtrerades.\n – Kontrollera internetanslutningen.\n – Kontrollera att du inte stavade e-postadressen fel.\n – Kontrollera att du inte har ont om utrymme i inkorgen eller andra inkorgsrelaterade problem.\n Om ovanstående lösningar inte fungerar kan du testa att skicka meddelandet igen. Länken i det gamla meddelandet inaktiveras om du gör det."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Ett inloggningsmeddelande med instruktioner skickades till %@. Kontrollera din e-post för att slutföra inloggningen."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Inloggningsmeddelande skickat"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ta.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ta.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..eeebad5c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ta.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "வரவேற்கிறோம்"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "மின்னஞ்சல் மூலம் உள்நுழைக"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "மின்னஞ்சலை உள்ளிடவும்"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "மின்னஞ்சல் முகவரி தவறாக உள்ளது."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "இந்தப் பயன்பாடு, இந்தக் கணக்கு வகையை ஆதரிக்காது"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "ஏற்கனவே உங்களிடம் கணக்கு உள்ளது"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "ஏற்கனவே %@ஐப் பயன்படுத்தியுள்ளீர்கள். தொடர, %@ மூலம் உள்நுழையவும்."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "உள்நுழைக"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "கடவுச்சொல்லை உள்ளிடவும்"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "கடவுச்சொல் காலியாக இருக்கக்கூடாது."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "உள்ளிட்ட மின்னஞ்சலும் கடவுச்சொல்லும் பொருந்தவில்லை."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "மின்னஞ்சல் முகவரி தற்போதைய கணக்குடன் பொருந்தவில்லை."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "இந்த மின்னஞ்சலுக்குரிய கணக்கு முடக்கப்பட்டுள்ளது."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "தவறான கடவுச்சொல்லைப் பலமுறை உள்ளிட்டுள்ளீர்கள். சில நிமிடங்களில் மீண்டும் முயலவும்."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@க்கான வழங்குநர் இல்லை."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "மின்னஞ்சல்கள் பொருந்தவில்லை"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "கடவுச்சொல்லை மீட்டெடு"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "கடவுச்சொல்லை மீட்டமைப்பது தொடர்பான வழிமுறைகளை இந்த மின்னஞ்சலில் பார்க்கவும்."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "உங்கள் மின்னஞ்சலைப் பார்க்கவும்"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "கடவுச்சொல்லை மீட்டெடுக்க, %@க்கு அனுப்பிய வழிமுறைகளைப் பின்பற்றவும்."; + +/* Title for sign up screen. */ +"SignUpTitle" = "கணக்கை உருவாக்கு"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "பெயரின் முற்பகுதி மற்றும் பிற்பகுதி"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "கடவுச்சொல்லைத் தேர்வு செய்யவும்"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "சேவை விதிமுறைகள்"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "தனியுரிமைக் கொள்கை"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "தொடர்வதன் மூலம், எங்கள் %@ மற்றும் %@ ஆகியவற்றை ஏற்பதாகக் குறிப்பிடுகிறீர்கள்."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "மின்னஞ்சல் முகவரி ஏற்கனவே வேறொரு கணக்கில் பயன்படுத்தப்படுகிறது."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "வலுவான கடவுச்சொற்களில் குறைந்தது 6 எழுத்துக்குறிகளும், எழுத்துகளும் எண்களும் கலந்த கலவையும் இருக்க வேண்டும்."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "உங்கள் IP முகவரியிலிருந்து கணக்குக் கோரிக்கைகள் பல வருகின்றன. சில நிமிடங்களில் மீண்டும் முயலவும்."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "ஏற்கனவே %@ஐப் பயன்படுத்தி உள்நுழைந்துள்ளீர்கள். அந்தக் கணக்கிற்கான கடவுச்சொல்லை உள்ளிடவும்."; + +/* OK button title. */ +"OK" = "சரி"; + +/* Cancel button title. */ +"Cancel" = "ரத்துசெய்"; + +/* Back button title. */ +"Back" = "முந்தையது"; + +/* Next button title. */ +"Next" = "அடுத்து"; + +/* Save button title. */ +"Save" = "சேமி"; + +/* Send button title. */ +"Send" = "அனுப்பு"; + +/* Resend button title. */ +"Resend" = "மீண்டும் அனுப்பு"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "மின்னஞ்சல்"; + +/* Label next to a password text field. */ +"Password" = "கடவுச்சொல்"; + +/* Label next to a name text field. */ +"Name" = "பெயர்"; + +/* Alert title Error. */ +"Error" = "பிழை"; + +/* Alert button title Close. */ +"Close" = "மூடு"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "சுயவிவரம்"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "பாதுகாப்பு"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "இணைத்துள்ள கணக்குகள்"; + +/* Account Settings cell title Name. */ +"AS_Name" = "பெயர்"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "மின்னஞ்சல்"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "கடவுச்சொல்லைச் சேர்"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "கடவுச்சொல்லை மாற்று"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "வெளியேறு"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "கணக்கை நீக்கு"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "கடவுச்சொல்லை மறந்துவிட்டீர்களா?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "நீங்கள் தான் என்பதை உறுதிசெய்யவும்"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "கணக்கை நீக்கவா?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "இவ்வாறு செய்தால், உங்கள் கணக்குடன் தொடர்புடைய எல்லாத் தரவும் அழிக்கப்படும், அத்துடன் அவற்றைத் திரும்பப்பெற முடியாது. இந்தச் செயல்பாட்டை முடிக்க, நீங்கள் மீண்டும் உள்நுழைய வேண்டும்"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "இவ்வாறு செய்தால், உங்கள் கணக்குடன் தொடர்புடைய எல்லாத் தரவும் அழிக்கப்படும், அத்துடன் அவற்றைத் திரும்பப்பெற முடியாது. நிச்சயம் நீக்க விரும்புகிறீர்களா?"; + +/* Text of Delete action button. */ +"Delete" = "நீக்கு"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "கணக்கை நீக்கு"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "இதைப் பின்னர் செயல்தவிர்க்க முடியாது"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "இணைப்பை நீக்கு"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "இணைத்துள்ள கணக்கு"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "கணக்கின் இணைப்பை நீக்கவா?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "உங்கள் கணக்கைப் பயன்படுத்தி இனி உள்நுழைய முடியாது"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "கணக்கின் இணைப்பை நீக்கு"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "உங்கள் கணக்குடன் தொடர்புடைய மின்னஞ்சல் முகவரியை மாற்ற, நீங்கள் மீண்டும் உள்நுழைய வேண்டும்."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "கடவுச்சொல்லை மாற்ற, தற்போதைய கடவுச்சொல்லை முதலில் உள்ளிட வேண்டும்."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "மின்னஞ்சலைத் திருத்து"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "பெயரை மாற்று"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "உங்கள் கணக்கின் கடவுச்சொல்லை சேர்க்க, நீங்கள் மீண்டும் உள்நுழைய வேண்டும்."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "உங்கள் கணக்கின் கடவுச்சொல்லை மாற்ற, நீங்கள் மீண்டும் உள்நுழைய வேண்டும்."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "கடவுச்சொல்லை மாற்ற, தற்போதைய கடவுச்சொல்லை முதலில் உள்ளிட வேண்டும்."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "கடவுச்சொல்லைச் சேர்"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "கடவுச்சொல்லை மாற்று"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "மின்னஞ்சல்"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ மூலம் உள்நுழைக"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "பெயரை உள்ளிடவும்"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "மின்னஞ்சலை உள்ளிடவும்"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "கடவுச்சொல்லை உள்ளிடவும்"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "புதிய கடவுச்சொல்"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "கடவுச்சொல்லைத் தேர்வு செய்யவும்"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "உள்நுழைவதில் சிக்கலா?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "மின்னஞ்சலை உறுதிப்படுத்தவும்"; + +/* Title of successfully signed in label. */ +"SignedIn" = "உள்நுழைந்துவிட்டீர்கள்!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "மின்னஞ்சல்களைப் பெறுவதில் சிக்கல் உள்ளதா?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "இந்தப் பொதுவான திருத்தங்களை முயலவும்: \n - மின்னஞ்சல் ஸ்பேமாகக் குறிக்கப்பட்டுள்ளதா அல்லது வடிகட்டப்பட்டுள்ளதா எனப் பார்க்கவும்.\n - இணைய இணைப்பைச் சரிபார்க்கவும்.\n - உங்கள் மின்னஞ்சல் முகவரியில் எழுத்துப்பிழை இல்லை என்பதை உறுதிப்படுத்திக் கொள்ளவும்.\n - இன்பாக்ஸில் போதுமான இடமுள்ளதா என்பதையும், மற்ற இன்பாக்ஸ் அமைப்புகளுடன் தொடர்புடைய சிக்கல்களையும் சரிபார்க்கவும்.\n மேலேயுள்ளவற்றை முயன்றும் பலனளிக்கவில்லை எனில், நீங்கள் மீண்டும் மின்னஞ்சல் அனுப்பலாம். இது முந்தைய மின்னஞ்சலில் உள்ள இணைப்பை முடக்கிவிடும் என்பதை நினைவில் கொள்ளவும்."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "கூடுதல் வழிமுறைகளுடன் கூடிய உள்நுழைவு மின்னஞ்சல் %@ என்பதற்கு அனுப்பப்பட்டது. உள்நுழைவை நிறைவு செய்ய, உங்கள் மின்னஞ்சலைப் பார்க்கவும்."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "உள்நுழைவு மின்னஞ்சல் அனுப்பப்பட்டது"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/th.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/th.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..ad6e9889 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/th.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "ยินดีต้อนรับ"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ลงชื่อเข้าใช้ด้วยอีเมล"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "ป้อนอีเมลของคุณ"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "ที่อยู่อีเมลนี้ไม่ถูกต้อง"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "แอปนี้ไม่รองรับบัญชีประเภทนี้"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "คุณมีบัญชีอยู่แล้ว"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "คุณใช้ %@ อยู่แล้ว ลงชื่อเข้าใช้ด้วย %@ เพื่อดำเนินการต่อ"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "ลงชื่อเข้าใช้"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "ป้อนรหัสผ่าน"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "ต้องระบุรหัสผ่าน"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "อีเมลและรหัสผ่านที่ป้อนไม่ตรงกัน"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "ที่อยู่อีเมลไม่ตรงกับบัญชีที่มีอยู่"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "ที่อยู่อีเมลนี้เป็นของบัญชีที่ปิดใช้ไปแล้ว"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "คุณป้อนรหัสผ่านไม่ถูกต้องหลายครั้งเกินไป โปรดรอสักครู่แล้วลองอีกครั้ง"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "ไม่พบผู้ให้บริการสำหรับ %@"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "อีเมลไม่ตรงกัน"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "กู้คืนรหัสผ่าน"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "ดูวิธีการที่ส่งไปยังอีเมลนี้ซึ่งอธิบายเกี่ยวกับวิธีรีเซ็ตรหัสผ่านของคุณ"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "ตรวจสอบอีเมลของคุณ"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "ทำตามวิธีการที่ส่งไปยัง %@ เพื่อกู้คืนรหัสผ่าน"; + +/* Title for sign up screen. */ +"SignUpTitle" = "สร้างบัญชี"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "ชื่อและนามสกุล"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "ตั้งรหัสผ่าน"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "ข้อกำหนดในการให้บริการ"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "นโยบายความเป็นส่วนตัว"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "การดำเนินการต่อแสดงว่าคุณยอมรับ%@และ%@"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "มีบัญชีอื่นใช้งานที่อยู่อีเมลนี้อยู่แล้ว"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "รหัสผ่านที่รัดกุมต้องมีความยาวอย่างน้อย 6 อักขระและประกอบด้วยตัวอักษรปนกับตัวเลข"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "มีคำขอสร้างบัญชีจากที่อยู่ IP ของคุณมากเกินไป โปรดรอสักครู่แล้วลองอีกครั้ง"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "คุณใช้ %@ ในการลงชื่อเข้าใช้อยู่แล้ว โปรดป้อนรหัสผ่านสำหรับบัญชีดังกล่าว"; + +/* OK button title. */ +"OK" = "ตกลง"; + +/* Cancel button title. */ +"Cancel" = "ยกเลิก"; + +/* Back button title. */ +"Back" = "ย้อนกลับ"; + +/* Next button title. */ +"Next" = "ถัดไป"; + +/* Save button title. */ +"Save" = "บันทึก"; + +/* Send button title. */ +"Send" = "ส่ง"; + +/* Resend button title. */ +"Resend" = "ส่งซ้ำ"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "อีเมล"; + +/* Label next to a password text field. */ +"Password" = "รหัสผ่าน"; + +/* Label next to a name text field. */ +"Name" = "ชื่อ"; + +/* Alert title Error. */ +"Error" = "ข้อผิดพลาด"; + +/* Alert button title Close. */ +"Close" = "ปิด"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "โปรไฟล์"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "ความปลอดภัย"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "บัญชีที่ลิงก์"; + +/* Account Settings cell title Name. */ +"AS_Name" = "ชื่อ"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "อีเมล"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "เพิ่มรหัสผ่าน"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "เปลี่ยนรหัสผ่าน"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "ออกจากระบบ"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "ลบบัญชี"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "หากลืมรหัสผ่าน"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "โปรดยืนยันว่าเป็นคุณ"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "ลบบัญชีไหม"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "การทำเช่นนี้จะลบข้อมูลทั้งหมดที่เชื่อมโยงกับบัญชีของคุณและไม่สามารถเลิกทำได้ โปรดลงชื่อเข้าใช้อีกครั้งเพื่อดำเนินการให้เสร็จสมบูรณ์"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "การทำเช่นนี้จะลบข้อมูลทั้งหมดที่เชื่อมโยงกับบัญชีและไม่สามารถเลิกทำได้ คุณแน่ใจไหมว่าต้องการลบบัญชีของคุณ"; + +/* Text of Delete action button. */ +"Delete" = "ลบ"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "ลบบัญชี"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "การดำเนินการนี้ไม่สามารถเลิกทำได้"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "ยกเลิกการลิงก์"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "บัญชีที่ลิงก์"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "ยกเลิกการลิงก์บัญชีไหม"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "คุณจะไม่สามารถลงชื่อเข้าใช้ด้วยบัญชีของคุณได้อีก"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "ยกเลิกการลิงก์บัญชี"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "ในการเปลี่ยนที่อยู่อีเมลที่เชื่อมโยงกับบัญชีของคุณ คุณจะต้องลงชื่อเข้าใช้อีกครั้ง"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "คุณต้องป้อนรหัสผ่านปัจจุบันของคุณก่อนจึงจะเปลี่ยนรหัสผ่านได้"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "แก้ไขอีเมล"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "แก้ไขชื่อ"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "ในการเพิ่มรหัสผ่านลงในบัญชี คุณจะต้องลงชื่อเข้าใช้อีกครั้ง"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "ในการเปลี่ยนรหัสผ่านบัญชี คุณจะต้องลงชื่อเข้าใช้อีกครั้ง"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "คุณต้องป้อนรหัสผ่านปัจจุบันของคุณก่อนจึงจะเปลี่ยนรหัสผ่านได้"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "เพิ่มรหัสผ่าน"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "เปลี่ยนรหัสผ่าน"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "อีเมล"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "ลงชื่อเข้าใช้ด้วย %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "ป้อนชื่อของคุณ"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "ป้อนอีเมลของคุณ"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "ป้อนรหัสผ่าน"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "รหัสผ่านใหม่"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "ตั้งรหัสผ่าน"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "หากพบปัญหาในการลงชื่อเช้าใช้"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ยืนยันอีเมล"; + +/* Title of successfully signed in label. */ +"SignedIn" = "ลงชื่อเข้าใช้แล้ว"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "มีปัญหาในการรับอีเมลใช่ไหม"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "ลองใช้วิธีแก้ไขทั่วไปเหล่านี้ \n - ตรวจสอบว่าอีเมลดังกล่าวมีการทำเครื่องหมายว่าเป็นสแปมหรือผ่านการกรอง\n - ตรวจสอบการเชื่อมต่ออินเทอร์เน็ต\n - ตรวจสอบว่าสะกดชื่ออีเมลถูกต้องแล้ว\n - ตรวจสอบว่ายังมีพื้นที่เหลือในกล่องจดหมายหรือไม่มีปัญหาอื่นๆ ที่เกี่ยวข้องกับการตั้งค่ากล่องจดหมาย\n คุณอาจส่งอีเมลอีกครั้งได้ หากขั้นตอนข้างต้นไม่ช่วยแก้ไขปัญหา โปรดทราบว่าการกระทำดังกล่าวจะเป็นการปิดใช้งานลิงก์ในอีเมลเก่า"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "ระบบได้ส่งอีเมลลงชื่อเข้าใช้พร้อมวิธีการเพิ่มเติมไปยัง %@ แล้ว โปรดตรวจสอบอีเมลเพื่อลงชื่อเข้าใช้"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "ส่งอีเมลลงชื่อเข้าใช้แล้ว"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/tr.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/tr.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..dc2df607 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/tr.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Hoş geldiniz"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "E-posta ile oturum aç"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "E-postanızı girin"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Bu e-posta adresi doğru değil."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Bu hesap türü, bu uygulama tarafından desteklenmiyor"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Zaten bir hesabınız var"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "%@ e-posta adresini daha önce kullandınız. Devam etmek için %@ ile oturum açın."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Oturum aç"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Şifrenizi girin"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Şifre boş bırakılamaz."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Girdiğiniz e-posta ile şifre eşleşmiyor."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Bu e-posta adresi mevcut bir hesapla eşleşmiyor."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Bu e-posta adresi, devre dışı bırakılmış bir hesaba ait."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Çok fazla kez yanlış şifre girdiniz. Birkaç dakika içinde tekrar deneyin."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ için sağlayıcı bulunamıyor."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "E-postalar eşleşmiyor"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Şifreyi kurtarın"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Şifrenizi nasıl sıfırlayacağınızı açıklayan talimatlar bu e-postaya gönderilsin."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "E-postanızı kontrol edin"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Şifrenizi kurtarmak için %@ adresine gönderilen talimatları uygulayın."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Hesap oluşturun"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Ad ve Soyadı"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Şifre seçin"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Hizmet Şartları"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Gizlilik Politikası"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Devam ederek %@ ve %@ hükümlerimizi kabul ettiğinizi bildirirsiniz."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "E-posta adresi başka bir hesap tarafından kullanılıyor."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Güçlü şifreler en az 6 karakterden oluşur ve hem harf hem de rakam içerir."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "IP adresinizden çok fazla sayıda hesap isteği geliyor. Birkaç dakika içinde tekrar deneyin."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Oturum açmak için %@ adresini zaten kullandınız. Bu hesaba ait şifrenizi girin."; + +/* OK button title. */ +"OK" = "Tamam"; + +/* Cancel button title. */ +"Cancel" = "İptal"; + +/* Back button title. */ +"Back" = "Geri"; + +/* Next button title. */ +"Next" = "İleri"; + +/* Save button title. */ +"Save" = "Kaydet"; + +/* Send button title. */ +"Send" = "Gönder"; + +/* Resend button title. */ +"Resend" = "Tekrar gönder"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "E-posta"; + +/* Label next to a password text field. */ +"Password" = "Şifre"; + +/* Label next to a name text field. */ +"Name" = "Ad"; + +/* Alert title Error. */ +"Error" = "Hata"; + +/* Alert button title Close. */ +"Close" = "Kapat"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Profil"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Güvenlik"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Bağlı Hesaplar"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Ad"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "E-posta"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Şifre ekle"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Şifreyi değiştir"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Oturumu Kapat"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Hesabı Sil"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Şifrenizi mi unuttunuz?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Kimliğinizi doğrulayın"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Hesap silinsin mi?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Bu işlem, hesabınızla ilişkili tüm verileri siler ve geri alınamaz. Bu işlemi tamamlamak için tekrar oturum açmanız gerekir"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Bu işlem, hesabınızla ilişkili tüm verileri siler ve geri alınamaz. Hesabınızı silmek istediğinizden emin misiniz?"; + +/* Text of Delete action button. */ +"Delete" = "Sil"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Hesabı silin"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Bu işlem geri alınamaz"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Bağlantıyı kaldır"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Bağlı hesap"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Hesabın bağlantısı kaldırılsın mı?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Artık hesabınızı kullanarak oturum açamazsınız"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Hesabın bağlantısını kaldırın"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Hesabınızla ilişkilendirilmiş e-posta adresini değiştirmek için tekrar oturum açmanız gerekir."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Şifrenizi değiştirmek için önce mevcut şifrenizi girmeniz gerekir."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "E-postayı düzenleyin"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Adı düzenleyin"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Hesabınıza şifre eklemek için tekrar oturum açmanız gerekir."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Hesabınızın şifresini değiştirmek için tekrar oturum açmanız gerekir."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Şifrenizi değiştirmek için önce mevcut şifrenizi girmeniz gerekir."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Şifre ekleyin"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Şifreyi değiştirin"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "E-posta"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ ile oturum aç"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Adınızı girin"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "E-postanızı girin"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Şifrenizi girin"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Yeni şifre"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Şifre seçin"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Oturum açılamıyor mu?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "E-posta Adresini Onaylayın"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Oturum açıldı!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "E-postaları almayla ilgili sorun mu yaşıyorsunuz?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Şu sık başvurulan düzeltme yöntemlerini deneyin: \n - E-postanın spam olarak işaretlenme veya filtrelenme durumunu kontrol edin.\n - İnternet bağlantınızı kontrol edin.\n - E-postanızda yazım hatası bulunmadığından emin olun.\n - Gelen kutunuzdaki boş alanın azalıp azalmadığını ve gelen kutusu ayarlarıyla ilgili başka bir sorun olup olmadığını kontrol edin.\n Yukarıdaki adımlar işe yaramazsa e-postayı yeniden gönderebilirsiniz. Bu işlemin eski e-postadaki bağlantıyı devre dışı bırakacağını göz önünde bulundurun."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "%@ adresine ek talimatlar içeren bir oturum açma e-postası gönderildi. Oturum açma işlemini tamamlamak için e-postanızı kontrol edin."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Oturum açma e-postası gönderildi"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/uk.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/uk.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..7950eacd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/uk.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Вітаємо"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Увійти, використовуючи електронну адресу"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Введіть електронну адресу"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Електронна адреса неправильна."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Додаток не підтримує облікові записи цього типу"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "У вас уже є обліковий запис"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Ви вже використовували електронну адресу %@. Щоб продовжити, увійдіть через %@."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Увійти"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Введіть пароль"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Укажіть пароль."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Електронна адреса та пароль не збігаються."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Ця електронна адреса не відповідає адресі наявного облікового запису."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Це електронна адреса вимкненого облікового запису."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Ви ввели неправильний пароль забагато разів. Спробуйте за кілька хвилин."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Не вдалося знайти постачальника для %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Електронні адреси не збігаються"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Відновити пароль"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "На цю електронну адресу надійдуть інструкції, як скинути пароль."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Перевірте свою електронну пошту"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Виконайте інструкції з відновлення пароля, надіслані на адресу %@."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Створити обліковий запис"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Ім’я та прізвище"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Виберіть пароль"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Умови використання"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Політика конфіденційності"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Продовжуючи, ви приймаєте такі документи: %@ і %@."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Ця електронна адреса вже використовується для іншого облікового запису."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Надійний пароль має містити принаймні 6 символів та комбінацію літер і цифр."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "З вашої IP-адреси надходить дуже багато запитів на створення облікового запису. Спробуйте за кілька хвилин."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Ви вже використовували адресу %@ для входу. Введіть пароль для цього облікового запису."; + +/* OK button title. */ +"OK" = "ОК"; + +/* Cancel button title. */ +"Cancel" = "Скасувати"; + +/* Back button title. */ +"Back" = "Назад"; + +/* Next button title. */ +"Next" = "Далі"; + +/* Save button title. */ +"Save" = "Зберегти"; + +/* Send button title. */ +"Send" = "Надіслати"; + +/* Resend button title. */ +"Resend" = "Надіслати ще раз"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Електронна адреса"; + +/* Label next to a password text field. */ +"Password" = "Пароль"; + +/* Label next to a name text field. */ +"Name" = "Ім’я"; + +/* Alert title Error. */ +"Error" = "Помилка"; + +/* Alert button title Close. */ +"Close" = "Закрити"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Профіль"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Безпека"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Зв’язані облікові записи"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Назва"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Електронна адреса"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Додати пароль"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Змінити пароль"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Вийти"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Видалити обліковий запис"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Забули пароль?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Підтвердьте свою особу"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Видалити обліковий запис?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Усі дані вашого облікового запису буде стерто, і цю дію не можна буде відмінити. Щоб виконати цю дію, потрібно ввійти ще раз."; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Усі дані вашого облікового запису буде стерто, і цю дію не можна буде відмінити. Видалити обліковий запис?"; + +/* Text of Delete action button. */ +"Delete" = "Видалити"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Видалити обліковий запис"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Цю дію не можна відмінити"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Від’єднати"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Зв’язаний обліковий запис"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Від’єднати обліковий запис?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Ви більше не зможете входити, використовуючи свій обліковий запис"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Від’єднати обліковий запис"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Щоб змінити електронну адресу, зв’язану з вашим обліковим записом, потрібно ввійти ще раз."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Щоб змінити пароль, спершу введіть поточний."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Змінити електронну адресу"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Змінити ім’я"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Щоб додати пароль до облікового запису, потрібно ввійти ще раз."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Щоб змінити пароль облікового запису, потрібно ввійти ще раз."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Щоб змінити пароль, спершу введіть поточний."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Додати пароль"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Змінити пароль"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Електронна адреса"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Твіттер"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Увійти, використовуючи %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Введіть своє ім’я"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Введіть електронну адресу"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Введіть пароль"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Новий пароль"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Виберіть пароль"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Не вдається ввійти?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Підтвердьте електронну адресу"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Ви ввійшли"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Ви не отримуєте електронні листи?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Щоб вирішити проблему, скористайтеся порадами нижче. \n – Перевірте: можливо, електронний лист позначено як спам або відфільтровано.\n – Перевірте інтернет-з’єднання.\n – Переконайтеся, що ви правильно вказали електронну адресу.\n – Перевірте доступний обсяг пам’яті для папки \"Вхідні\" й інші можливі проблеми з налаштуваннями.\n – Якщо поради вище не допоможуть, надішліть електронний лист повторно. Зверніть увагу, що після цього посилання в давнішому електронному листі стане недійсним."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Посилання для входу та додаткові вказівки надіслано на адресу %@. Дотримуйтеся їх, щоб увійти в обліковий запис."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Електронну адресу для входу надіслано"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ur.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ur.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..1e94ae6b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/ur.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "خوش آمدید"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "ای میل کے ساتھ سائن ان کریں"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "اپنا ای میل درج کریں"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "یہ ای میل پتہ غلط ہے۔"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "اس قسم کا اکاؤنٹ اس ایپ کی جانب سے تعاون یافتہ نہیں ہے"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "آپ کے پاس پہلے سے ہی ایک اکاؤنٹ موجود ہے"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "آپ نے پہلے ہی %@ کو استعمال کر لیا ہے۔ جاری رکھنے کے لیے %@ کے ساتھ سائن ان کریں۔"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "سائن ان کریں"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "اپنا پاس ورڈ درج کریں"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "پاس ورڈ خالی نہیں ہو سکتا۔"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "آپ نے جو ای میل اور پاس ورڈ درج کیا ہے وہ مماثل نہیں ہیں۔"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "یہ ای میل پتہ کسی موجودہ اکاؤنٹ کے مماثل نہیں ہے۔"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "یہ ای میل پتہ ایک غیر فعال کیے ہوئے اکاؤنٹ کے لیے ہے۔"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "آپ نے ایک غلط پاس ورڈ کافی مرتبہ درج کیا ہے۔ چند منٹوں میں دوبارہ کوشش کریں۔"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "%@ کے لیے فراہم کنندہ کو تلاش نہیں کر سکتے۔"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "ای میلز مماثل نہیں ہیں"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "پاس ورڈ بازیافت کریں"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "اس ای میل پر بھیجی گئی وہ ہدایات حاصل کریں جن میں آپ کے پاس ورڈ کو دوبارہ ترتیب دینے کے طریقے کی وضاحت ہے۔"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "اپنا ای میل چیک کریں"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "اپنے پاس ورڈ کو بازیافت کرنے کے لیے %@ پر بھیجی گئی ہدایات کی پیروی کریں۔"; + +/* Title for sign up screen. */ +"SignUpTitle" = "اکاؤنٹ بنائیں"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "پہلا اور آخری نام"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "پاس ورڈ منتخب کریں"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "سروس کی شرائط"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "رازداری کی پالیسی"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "جاری رکھ کر، آپ نشاندہی کر رہے ہیں کہ آپ ہماری %@ اور %@ کو قبول کرتے ہیں۔"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "یہ ای میل پتہ پہلے سے ہی دوسرے اکاؤنٹ کے زیر استعمال ہے۔"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "مضبوط پاس ورڈز میں کم از کم 6 کریکٹرز اور حروف و اعداد کا مرکب ہوتے ہیں۔"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "اکاؤنٹ کی بہت سی درخواستیں آپ کے IP پتے سے آ رہی ہیں۔ چند منٹوں میں دوبارہ کوشش کریں۔"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "آپ نے پہلے ہی سائن ان کرنے کے لیے %@ کو استعمال کر لیا ہے۔ اس اکاؤنٹ کے لیے اپنا پاس ورڈ درج کریں۔"; + +/* OK button title. */ +"OK" = "ٹھیک ہے"; + +/* Cancel button title. */ +"Cancel" = "منسوخ کریں"; + +/* Back button title. */ +"Back" = "پیچھے جائیں"; + +/* Next button title. */ +"Next" = "آگے جائیں"; + +/* Save button title. */ +"Save" = "محفوظ کریں"; + +/* Send button title. */ +"Send" = "بھیجیں"; + +/* Resend button title. */ +"Resend" = "دوبارہ بھیجیں"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "ای میل"; + +/* Label next to a password text field. */ +"Password" = "پاس ورڈ"; + +/* Label next to a name text field. */ +"Name" = "نام"; + +/* Alert title Error. */ +"Error" = "خرابی"; + +/* Alert button title Close. */ +"Close" = "بند کریں"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "پروفائل"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "سیکیورٹی"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "لنک کردہ اکاؤنٹس"; + +/* Account Settings cell title Name. */ +"AS_Name" = "نام"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "ای میل"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "پاس ورڈ شامل کریں"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "پاس ورڈ تبدیل کریں"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "سائن آؤٹ کریں"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "اکاؤنٹ حذف کریں"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "پاس ورڈ بھول گئے؟"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "توثیق کریں کہ یہ آپ ہی ہیں"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "اکاؤنٹ حذف کریں؟"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "یہ آپ کے اکاؤنٹ سے وابستہ سبھی ڈیٹا کو مٹا دے گا، اور کالعدم نہیں ہوسکتا۔ آپ کو یہ عمل مکمل کرنے کے لیے دوبارہ سائن ان کرنے کی ضرورت پڑے گی"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "یہ آپ کے اکاؤنٹ سے وابستہ سبھی ڈیٹا کو مٹا دے گا، اور کالعدم نہیں ہوسکتا۔ کیا آپ واقعی اپنا اکاؤنٹ حذف کرنا چاہتے ہیں؟"; + +/* Text of Delete action button. */ +"Delete" = "حذف کریں"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "اکاؤنٹ حذف کریں"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "اس عمل کو کالعدم نہیں کیا جا سکتا"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "لنک ختم کریں"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "لنک کردہ اکاؤنٹ"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "اکاؤنٹ کا لنک ختم کریں؟"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "اب آپ اپنا اکاؤنٹ استعمال کرتے ہوئے سائن ان نہیں کر سکیں گے"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "اکاؤنٹ کا لنک ختم کریں"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "اپنے اکاؤنٹ سے وابستہ ای میل پتہ تبدیل کرنے کے لیے، آپ کو دوبارہ سائن ان کرنے کی ضرورت پڑے گی۔"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "اپنا پاس ورڈ تبدیل کرنے کے لیے، پہلے آپ کو اپنا موجودہ پاس ورڈ درج کرنے کی ضرورت ہے۔"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "ای میل میں ترمیم کریں"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "نام میں ترمیم کریں"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "اپنے اکاؤنٹ میں پاس ورڈ شامل کرنے کے لیے، آپ کو دوبارہ سائن ان کرنے کی ضرورت ہے۔"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "اپنے اکاؤنٹ کا پاس ورڈ تبدیل کرنے کے لیے، آپ کو دوبارہ سائن ان کرنے کی ضرورت ہے۔"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "اپنا پاس ورڈ تبدیل کرنے کے لیے، پہلے آپ کو اپنا موجودہ پاس ورڈ درج کرنے کی ضرورت ہے۔"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "پاس ورڈ شامل کریں"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "پاس ورڈ تبدیل کریں"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "ای میل"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "%@ کے ساتھ سائن ان کریں"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "اپنا نام درج کریں"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "اپنا ای میل درج کریں"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "اپنا پاس ورڈ درج کریں"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "نیا پاس ورڈ"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "پاس ورڈ منتخب کریں"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "سائن ان کرنے میں دشواری؟"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "ای میل کی تصدیق کریں"; + +/* Title of successfully signed in label. */ +"SignedIn" = "سائن ان ہو گیا!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "ای میلز حاصل کرنے میں دشواری پیش آ رہی ہے؟"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "یہ عام اصلاحات آزمائیں: \n - چیک کریں کہ آیا ای میل سپام یا فلٹر شدہ کے طور پر نشان زد کی گئی ہے۔\n - اپنا انٹرنیٹ کنکشن چیک کریں۔\n - چیک کریں کہ آپ نے اپنی ای میل کے ہجے میں غلطی تو نہیں کی ہے۔\n - چیک کریں کہ آپ کی ان باکس اسپیس ختم تو نہیں ہوگئی ہے یا دیگر ان باکس کی ترتیبات سے متعلق مسائل چیک کریں۔\n اگر مندرجہ بالا مراحل کام نہ کریں تو آپ ای میل دوبارہ بھیج سکتے ہیں۔ نوٹ کریں کہ اس سے پرانی ای میل میں موجود لنک غیر فعال ہو جائے گا۔"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "ایک سائن ان ای میل اضافی ہدایات کے ساتھ %@ کو بھیج دی گئی ہے۔ سائن ان مکمل کرنے کے لیے اپنی ای میل چیک کریں۔"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "سائن ان ای میل بھیج دی گئی"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/vi.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/vi.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..9328159c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/vi.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "Chào mừng bạn"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "Đăng nhập bằng email"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "Nhập email của bạn"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "Địa chỉ email đó không đúng."; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "Loại tài khoản này không được ứng dụng này hỗ trợ"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "Bạn đã có tài khoản"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "Bạn đã sử dụng %@. Đăng nhập bằng %@ để tiếp tục."; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "Đăng nhập"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "Nhập mật khẩu của bạn"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "Không được để trống mật khẩu."; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "Email và mật khẩu bạn đã nhập không khớp."; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "Địa chỉ email đó không khớp với tài khoản hiện có."; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "Địa chỉ email đó là dành cho tài khoản đã bị vô hiệu hóa."; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "Bạn đã nhập sai mật khẩu quá nhiều lần. Hãy thử lại sau một vài phút."; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "Không thể tìm thấy nhà cung cấp cho %@."; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "Email không khớp"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "Khôi phục mật khẩu"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "Xem hướng dẫn gửi tới email này có giải thích cách đặt lại mật khẩu của bạn."; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "Kiểm tra email của bạn"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "Làm theo hướng dẫn gửi tới %@ để khôi phục mật khẩu của bạn."; + +/* Title for sign up screen. */ +"SignUpTitle" = "Tạo tài khoản"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "Họ và tên"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "Chọn mật khẩu"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "Điều khoản dịch vụ"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "Chính sách về quyền riêng tư"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "Bằng cách tiếp tục, bạn cho biết rằng bạn chấp nhận %@ và %@ của chúng tôi."; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "Địa chỉ email đã được tài khoản khác sử dụng."; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "Mật khẩu mạnh có ít nhất 6 ký tự, kết hợp chữ cái và số."; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "Có quá nhiều yêu cầu tài khoản từ địa chỉ IP của bạn. Hãy thử lại sau một vài phút."; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "Bạn đã sử dụng %@ để đăng nhập. Hãy nhập mật khẩu của bạn cho tài khoản đó."; + +/* OK button title. */ +"OK" = "OK"; + +/* Cancel button title. */ +"Cancel" = "Hủy"; + +/* Back button title. */ +"Back" = "Quay lại"; + +/* Next button title. */ +"Next" = "Tiếp"; + +/* Save button title. */ +"Save" = "Lưu"; + +/* Send button title. */ +"Send" = "Gửi"; + +/* Resend button title. */ +"Resend" = "Gửi lại"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "Email"; + +/* Label next to a password text field. */ +"Password" = "Mật khẩu"; + +/* Label next to a name text field. */ +"Name" = "Tên"; + +/* Alert title Error. */ +"Error" = "Lỗi"; + +/* Alert button title Close. */ +"Close" = "Đóng"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "Hồ sơ"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "Bảo mật"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "Tài khoản được liên kết"; + +/* Account Settings cell title Name. */ +"AS_Name" = "Tên"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "Email"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "Thêm mật khẩu"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "Đổi mật khẩu"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "Đăng xuất"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "Xóa tài khoản"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "Quên mật khẩu?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "Xác minh đó là bạn"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "Xóa tài khoản?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "Thao tác này sẽ xóa tất cả dữ liệu được liên kết với tài khoản của bạn và không thể hoàn tác. Bạn sẽ phải đăng nhập lại để hoàn tất thao tác này"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "Thao tác này sẽ xóa tất cả dữ liệu được liên kết với tài khoản của bạn và không thể hoàn tác. Bạn có chắc chắn muốn xóa tài khoản của bạn không?"; + +/* Text of Delete action button. */ +"Delete" = "Xóa"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "Xóa tài khoản"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "Không thể hoàn tác thao tác này"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "Hủy liên kết"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "Tài khoản được liên kết"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "Hủy liên kết tài khoản?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "Bạn sẽ không thể đăng nhập bằng tài khoản của bạn"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "Hủy liên kết tài khoản"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "Để thay đổi địa chỉ email liên kết với tài khoản của bạn, bạn sẽ phải đăng nhập lại."; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "Để thay đổi mật khẩu, trước tiên bạn phải nhập mật khẩu hiện tại của bạn."; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "Chỉnh sửa email"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "Chỉnh sửa tên"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "Để thêm mật khẩu cho tài khoản của bạn, bạn sẽ phải đăng nhập lại."; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "Để thay đổi mật khẩu cho tài khoản của bạn, bạn sẽ phải đăng nhập lại."; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "Để thay đổi mật khẩu, trước tiên bạn phải nhập mật khẩu hiện tại của bạn."; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "Thêm mật khẩu"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "Đổi mật khẩu"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "Email"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "Đăng nhập bằng %@"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "Nhập tên của bạn"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "Nhập email của bạn"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "Nhập mật khẩu của bạn"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "Mật khẩu mới"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "Chọn mật khẩu"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "Bạn gặp sự cố khi đăng nhập?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "Xác nhận email"; + +/* Title of successfully signed in label. */ +"SignedIn" = "Đã đăng nhập!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "Bạn gặp vấn đề khi nhận email?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "Hãy thử các cách khắc phục vấn đề phổ biến sau: \n - Kiểm tra xem email có bị đánh dấu là spam hay đã được lọc.\n - Kiểm tra kết nối Internet của bạn.\n - Kiểm tra để đảm bảo bạn không viết sai chính tả tên email.\n - Kiểm tra để đảm bảo dung lượng bộ nhớ hộp thư đến của bạn chưa hết hoặc không có vấn đề khác liên quan đến tùy chọn cài đặt hộp thư đến.\n Nếu các bước trên không hiệu quả, bạn có thể gửi lại email. Vui lòng lưu ý rằng thao tác này sẽ hủy kích hoạt đường dẫn liên kết trong email cũ."; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "Email đăng nhập có hướng dẫn bổ sung đã gửi tới %@. Hãy tìm email này trong hộp thư của bạn để hoàn tất đăng nhập."; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "Đã gửi email đăng nhập"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hans.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hans.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..4a21d4d2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hans.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "欢迎"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "使用电子邮件地址登录"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "输入您的电子邮件地址"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "该电子邮件地址不正确。"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "此应用不支持这种类型的帐号"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "您已经有帐号了"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "您已经使用了 %@。请使用 %@ 帐号登录以继续操作。"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "登录"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "输入您的密码"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "密码不能为空。"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "您输入的电子邮件地址和密码不匹配。"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "该电子邮件地址没有相匹配的现有帐号。"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "该电子邮件地址对应的帐号已停用。"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "您输入错误密码的次数过多,请过几分钟再试。"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "找不到 %@ 的提供方。"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "电子邮件地址不匹配"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "找回密码"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "向此电子邮件地址发送关于如何重置密码的说明。"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "请查收电子邮件"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "请按照发送到 %@ 的说明找回密码。"; + +/* Title for sign up screen. */ +"SignUpTitle" = "创建帐号"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "姓名"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "选择密码"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "服务条款"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "隐私权政策"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "继续即表示您接受我们的%@和%@。"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "此电子邮件地址已被其他帐号使用。"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "安全系数高的密码至少包含 6 个字符,由字母和数字组成。"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "来自您的 IP 地址的帐号请求过多,请过几分钟再试。"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "您已经使用 %@ 登录了,请输入该帐号的密码。"; + +/* OK button title. */ +"OK" = "确定"; + +/* Cancel button title. */ +"Cancel" = "取消"; + +/* Back button title. */ +"Back" = "返回"; + +/* Next button title. */ +"Next" = "继续"; + +/* Save button title. */ +"Save" = "保存"; + +/* Send button title. */ +"Send" = "发送"; + +/* Resend button title. */ +"Resend" = "重新发送"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "电子邮件"; + +/* Label next to a password text field. */ +"Password" = "密码"; + +/* Label next to a name text field. */ +"Name" = "名称"; + +/* Alert title Error. */ +"Error" = "错误"; + +/* Alert button title Close. */ +"Close" = "关闭"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "个人资料"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "安全"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "已关联的帐号"; + +/* Account Settings cell title Name. */ +"AS_Name" = "名称"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "电子邮件"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "添加密码"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "更改密码"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "退出帐号"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "删除帐号"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "忘记了密码?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "请验证是您本人"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "要删除帐号吗?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "此操作将清空与您的帐号相关联的所有数据,并且无法撤消。您需要重新登录才能完成此操作"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "此操作将清空与您的帐号相关联的所有数据,并且无法撤消。确定要删除帐号吗?"; + +/* Text of Delete action button. */ +"Delete" = "删除"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "删除帐号"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "此操作无法撤消"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "取消关联"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "已关联的帐号"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "要取消帐号关联吗?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "您将不能再使用您的帐号登录"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "取消帐号关联"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "要更改与您的帐号关联的电子邮件地址,您需要再次登录。"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "要更改密码,您需要先输入当前的密码。"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "修改电子邮件地址"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "修改名称"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "要为帐号添加密码,您需要重新登录。"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "要更改帐号的密码,您需要重新登录。"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "要更改密码,您需要先输入当前的密码。"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "添加密码"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "更改密码"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "电子邮件"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "使用 %@ 帐号登录"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "输入您的名称"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "输入您的电子邮件地址"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "输入您的密码"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "新密码"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "选择密码"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "登录时遇到问题?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "确认电子邮件地址"; + +/* Title of successfully signed in label. */ +"SignedIn" = "已登录!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "无法收到电子邮件?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "尝试以下常见解决方法:\n - 检查电子邮件是否被标记为垃圾邮件或被过滤。\n - 检查互联网连接。\n - 确保没有写错电子邮件地址。\n - 确保收件箱空间充足,且不存在其他与收件箱设置有关的问题。\n 如果上述步骤未能帮助您解决问题,您可以重新发送电子邮件。请注意,重新发送后上一封电子邮件中的链接将失效。"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "系统已将含附加说明的登录电子邮件发送至 %@。请查收电子邮件以完成登录。"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "已发送登录电子邮件"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant-TW.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant-TW.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..b46d7784 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant-TW.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "歡迎"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "使用電子郵件登入"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "輸入您的電子郵件"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "電子郵件地址不正確。"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "此應用程式不支援這種類型的帳戶"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "您已經有一個帳戶"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "您已經使用 %@。如要繼續進行,請登入 %@ 帳戶。"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "登入"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "輸入您的密碼"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "密碼不能空白。"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "您輸入的電子郵件和密碼不相符。"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "這個電子郵件地址和現有帳戶不相符。"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "這個電子郵件地址屬於已停用的帳戶。"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "您輸入錯誤密碼的次數過多,請於幾分鐘後再試一次。"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "找不到 %@ 的供應商。"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "電子郵件不相符"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "重新取得密碼"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "這個電子郵件會收到重設密碼的指示。"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "請查看您的電子郵件"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "請依照傳送至 %@ 的指示重新取得密碼。"; + +/* Title for sign up screen. */ +"SignUpTitle" = "建立帳戶"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "姓名"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "選擇密碼"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "服務條款"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "隱私權政策"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "選擇繼續即表示您接受我們的《%@》和《%@》。"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "另一個帳戶已使用這個電子郵件地址。"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "安全強度高的密碼至少需有 6 個字元並混用字母和數字。"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "您的 IP 位址傳送建立帳戶要求的次數過多,請於幾分鐘後再試一次。"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "您已使用 %@ 帳戶登入,請輸入該帳戶的密碼。"; + +/* OK button title. */ +"OK" = "確定"; + +/* Cancel button title. */ +"Cancel" = "取消"; + +/* Back button title. */ +"Back" = "上一步"; + +/* Next button title. */ +"Next" = "下一步"; + +/* Save button title. */ +"Save" = "儲存"; + +/* Send button title. */ +"Send" = "傳送"; + +/* Resend button title. */ +"Resend" = "重新傳送"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "電子郵件"; + +/* Label next to a password text field. */ +"Password" = "密碼"; + +/* Label next to a name text field. */ +"Name" = "名稱"; + +/* Alert title Error. */ +"Error" = "錯誤"; + +/* Alert button title Close. */ +"Close" = "關閉"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "個人資料"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "安全性"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "已連結帳戶"; + +/* Account Settings cell title Name. */ +"AS_Name" = "名稱"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "電子郵件"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "新增密碼"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "變更密碼"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "登出"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "刪除帳戶"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "忘記密碼了嗎?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "請驗證您的身分"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "要刪除帳戶嗎?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "這項操作會清除與您的帳戶相關聯的所有資料,而且帳戶刪除後即無法復原。您需要再次登入才能完成這項操作"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "這項操作會清除與您的帳戶相關聯的所有資料,而且帳戶刪除後即無法復原。確定要刪除帳戶嗎?"; + +/* Text of Delete action button. */ +"Delete" = "刪除"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "刪除帳戶"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "這項操作無法復原"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "取消連結"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "已連結帳戶"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "要取消連結帳戶嗎?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "您將無法再使用自己的帳戶登入"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "取消連結帳戶"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "如要變更帳戶所連結的電子郵件地址,您需要重新登入帳戶。"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "如要變更密碼,請先輸入目前的密碼。"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "編輯電子郵件"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "編輯名稱"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "如要新增帳戶密碼,您需要重新登入。"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "如要變更帳戶密碼,您需要重新登入。"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "如要變更密碼,請先輸入目前的密碼。"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "新增密碼"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "變更密碼"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "電子郵件"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "使用 %@ 帳戶登入"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "輸入您的名稱"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "輸入您的電子郵件"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "輸入您的密碼"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "新密碼"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "選擇密碼"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "無法登入嗎?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "確認電子郵件地址"; + +/* Title of successfully signed in label. */ +"SignedIn" = "登入成功!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "沒收到電子郵件嗎?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "請試試這些常見的解決方式:\n - 檢查電子郵件是否被標示為垃圾郵件或遭系統篩除。\n - 檢查您的網際網路連線。\n - 檢查電子郵件地址是否拼錯。\n - 確認收件匣的儲存空間是否足夠,或檢查與收件匣設定相關的其他問題。\n 如果上述步驟全部無效,建議您重新傳送電子郵件。請注意,這個動作會使先前郵件中的連結失效。"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "系統已將登入電子郵件傳送至 %@,其中包含額外的操作說明。請查看您的電子郵件以完成登入程序。"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "已寄出登入電子郵件"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..b46d7784 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh-Hant.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "歡迎"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "使用電子郵件登入"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "輸入您的電子郵件"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "電子郵件地址不正確。"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "此應用程式不支援這種類型的帳戶"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "您已經有一個帳戶"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "您已經使用 %@。如要繼續進行,請登入 %@ 帳戶。"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "登入"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "輸入您的密碼"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "密碼不能空白。"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "您輸入的電子郵件和密碼不相符。"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "這個電子郵件地址和現有帳戶不相符。"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "這個電子郵件地址屬於已停用的帳戶。"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "您輸入錯誤密碼的次數過多,請於幾分鐘後再試一次。"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "找不到 %@ 的供應商。"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "電子郵件不相符"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "重新取得密碼"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "這個電子郵件會收到重設密碼的指示。"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "請查看您的電子郵件"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "請依照傳送至 %@ 的指示重新取得密碼。"; + +/* Title for sign up screen. */ +"SignUpTitle" = "建立帳戶"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "姓名"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "選擇密碼"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "服務條款"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "隱私權政策"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "選擇繼續即表示您接受我們的《%@》和《%@》。"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "另一個帳戶已使用這個電子郵件地址。"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "安全強度高的密碼至少需有 6 個字元並混用字母和數字。"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "您的 IP 位址傳送建立帳戶要求的次數過多,請於幾分鐘後再試一次。"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "您已使用 %@ 帳戶登入,請輸入該帳戶的密碼。"; + +/* OK button title. */ +"OK" = "確定"; + +/* Cancel button title. */ +"Cancel" = "取消"; + +/* Back button title. */ +"Back" = "上一步"; + +/* Next button title. */ +"Next" = "下一步"; + +/* Save button title. */ +"Save" = "儲存"; + +/* Send button title. */ +"Send" = "傳送"; + +/* Resend button title. */ +"Resend" = "重新傳送"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "電子郵件"; + +/* Label next to a password text field. */ +"Password" = "密碼"; + +/* Label next to a name text field. */ +"Name" = "名稱"; + +/* Alert title Error. */ +"Error" = "錯誤"; + +/* Alert button title Close. */ +"Close" = "關閉"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "個人資料"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "安全性"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "已連結帳戶"; + +/* Account Settings cell title Name. */ +"AS_Name" = "名稱"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "電子郵件"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "新增密碼"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "變更密碼"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "登出"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "刪除帳戶"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "忘記密碼了嗎?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "請驗證您的身分"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "要刪除帳戶嗎?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "這項操作會清除與您的帳戶相關聯的所有資料,而且帳戶刪除後即無法復原。您需要再次登入才能完成這項操作"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "這項操作會清除與您的帳戶相關聯的所有資料,而且帳戶刪除後即無法復原。確定要刪除帳戶嗎?"; + +/* Text of Delete action button. */ +"Delete" = "刪除"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "刪除帳戶"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "這項操作無法復原"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "取消連結"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "已連結帳戶"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "要取消連結帳戶嗎?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "您將無法再使用自己的帳戶登入"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "取消連結帳戶"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "如要變更帳戶所連結的電子郵件地址,您需要重新登入帳戶。"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "如要變更密碼,請先輸入目前的密碼。"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "編輯電子郵件"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "編輯名稱"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "如要新增帳戶密碼,您需要重新登入。"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "如要變更帳戶密碼,您需要重新登入。"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "如要變更密碼,請先輸入目前的密碼。"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "新增密碼"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "變更密碼"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "電子郵件"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "使用 %@ 帳戶登入"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "輸入您的名稱"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "輸入您的電子郵件"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "輸入您的密碼"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "新密碼"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "選擇密碼"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "無法登入嗎?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "確認電子郵件地址"; + +/* Title of successfully signed in label. */ +"SignedIn" = "登入成功!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "沒收到電子郵件嗎?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "請試試這些常見的解決方式:\n - 檢查電子郵件是否被標示為垃圾郵件或遭系統篩除。\n - 檢查您的網際網路連線。\n - 檢查電子郵件地址是否拼錯。\n - 確認收件匣的儲存空間是否足夠,或檢查與收件匣設定相關的其他問題。\n 如果上述步驟全部無效,建議您重新傳送電子郵件。請注意,這個動作會使先前郵件中的連結失效。"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "系統已將登入電子郵件傳送至 %@,其中包含額外的操作說明。請查看您的電子郵件以完成登入程序。"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "已寄出登入電子郵件"; diff --git a/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh.lproj/FirebaseAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh.lproj/FirebaseAuthUI.strings new file mode 100644 index 00000000..4a21d4d2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/Auth/FirebaseAuthUI/Strings/zh.lproj/FirebaseAuthUI.strings @@ -0,0 +1,269 @@ +/* Title for auth picker screen. */ +"AuthPickerTitle" = "欢迎"; + +/* Sign in with email button label. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"SignInWithEmail" = "使用电子邮件地址登录"; + +/* Title for email entry screen, email text field placeholder. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EnterYourEmail" = "输入您的电子邮件地址"; + +/* Error message displayed when user enters an invalid email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"InvalidEmailError" = "该电子邮件地址不正确。"; + +/* Error message displayed when the app cannot authenticate user's account. */ +"CannotAuthenticateError" = "此应用不支持这种类型的帐号"; + +/* Title of an alert shown to an existing user coming back to the app. */ +"ExistingAccountTitle" = "您已经有帐号了"; + +/* Alert message to let user know what identity provider (second placeholder, ex. Google) was used previously for the email address (first placeholder). */ +"ProviderUsedPreviouslyMessage" = "您已经使用了 %@。请使用 %@ 帐号登录以继续操作。"; + +/* Title for sign in screen and sign in button. */ +"SignInTitle" = "登录"; + +/* Password text field placeholder. */ +"EnterYourPassword" = "输入您的密码"; + +/* Error message displayed when user enters an empty password. */ +"InvalidPasswordError" = "密码不能为空。"; + +/* Error message displayed when the email and password don't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"WrongPasswordError" = "您输入的电子邮件地址和密码不匹配。"; + +/* Error message displayed when there's no account matching the email address. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UserNotFoundError" = "该电子邮件地址没有相匹配的现有帐号。"; + +/* Error message displayed when the account is disabled. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AccountDisabledError" = "该电子邮件地址对应的帐号已停用。"; + +/* Error message displayed after user trying to sign in too many times. */ +"SignInTooManyTimesError" = "您输入错误密码的次数过多,请过几分钟再试。"; + +/* Error message displayed when FUIAuth is not configured with third party provider. Parameter is value of provider (e g Google, Facebook etc) */ +"CantFindProvider" = "找不到 %@ 的提供方。"; + +/* Error message displayed when after re-authorization current user's email and re-authorized user's email doesn't match. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailsDontMatch" = "电子邮件地址不匹配"; + +/* Title for password recovery screen. */ +"PasswordRecoveryTitle" = "找回密码"; + +/* Explanation on how the password of an account can be recovered. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryMessage" = "向此电子邮件地址发送关于如何重置密码的说明。"; + +/* Title of a message displayed when the email for password recovery has been sent. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PasswordRecoveryEmailSentTitle" = "请查收电子邮件"; + +/* Message displayed when the email for password recovery has been sent. */ +"PasswordRecoveryEmailSentMessage" = "请按照发送到 %@ 的说明找回密码。"; + +/* Title for sign up screen. */ +"SignUpTitle" = "创建帐号"; + +/* Name text field placeholder. */ +"FirstAndLastName" = "姓名"; + +/* Placeholder for the password text field in a sign up form. */ +"ChoosePassword" = "选择密码"; + +/* Text linked to a web page with the Terms of Service content. */ +"TermsOfService" = "服务条款"; + +/* Text linked to a web page with the Privacy Policy content. */ +"PrivacyPolicy" = "隐私权政策"; + +/* A message displayed when the first log in screen is displayed. The first placeholder is the terms of service agreement link, the second place holder is the privacy policy agreement link. */ +"TermsOfServiceMessage" = "继续即表示您接受我们的%@和%@。"; + +/* Error message displayed when the email address is already in use. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EmailAlreadyInUseError" = "此电子邮件地址已被其他帐号使用。"; + +/* Error message displayed when the password is too weak. */ +"WeakPasswordError" = "安全系数高的密码至少包含 6 个字符,由字母和数字组成。"; + +/* Error message displayed when many accounts have been created from same IP address. */ +"SignUpTooManyTimesError" = "来自您的 IP 地址的帐号请求过多,请过几分钟再试。"; + +/* Message to explain to the user that password is needed for an account with this email address. */ +"PasswordVerificationMessage" = "您已经使用 %@ 登录了,请输入该帐号的密码。"; + +/* OK button title. */ +"OK" = "确定"; + +/* Cancel button title. */ +"Cancel" = "取消"; + +/* Back button title. */ +"Back" = "返回"; + +/* Next button title. */ +"Next" = "继续"; + +/* Save button title. */ +"Save" = "保存"; + +/* Send button title. */ +"Send" = "发送"; + +/* Resend button title. */ +"Resend" = "重新发送"; + +/* Label next to a email text field. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"Email" = "电子邮件"; + +/* Label next to a password text field. */ +"Password" = "密码"; + +/* Label next to a name text field. */ +"Name" = "名称"; + +/* Alert title Error. */ +"Error" = "错误"; + +/* Alert button title Close. */ +"Close" = "关闭"; + +/* Account Settings section title Profile. */ +"AS_SectionProfile" = "个人资料"; + +/* Account Settings section title Security. */ +"AS_SectionSecurity" = "安全"; + +/* Account Settings section title Linked Accounts. */ +"AS_SectionLinkedAccounts" = "已关联的帐号"; + +/* Account Settings cell title Name. */ +"AS_Name" = "名称"; + +/* Account Settings cell title Email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"AS_Email" = "电子邮件"; + +/* Account Settings cell title Add Password. */ +"AS_AddPassword" = "添加密码"; + +/* Account Settings cell title Change Password. */ +"AS_ChangePassword" = "更改密码"; + +/* Account Settings cell title Sign Out. */ +"AS_SignOut" = "退出帐号"; + +/* Account Settings cell title Delete Account. */ +"AS_DeleteAccount" = "删除帐号"; + +/* Button text for 'Forgot Password' action. */ +"ForgotPassword" = "忘记了密码?"; + +/* Alert message title show for re-authorization. */ +"VerifyItsYou" = "请验证是您本人"; + +/* Alert message title shown to confirm account deletion action. */ +"DeleteAccountConfirmationTitle" = "要删除帐号吗?"; + +/* Alert message body shown to confirm account deletion action. */ +"DeleteAccountBody" = "此操作将清空与您的帐号相关联的所有数据,并且无法撤消。您需要重新登录才能完成此操作"; + +/* Explanation message shown before deleting account. */ +"DeleteAccountConfirmationMessage" = "此操作将清空与您的帐号相关联的所有数据,并且无法撤消。确定要删除帐号吗?"; + +/* Text of Delete action button. */ +"Delete" = "删除"; + +/* Title of Controller shown before deleting account */ +"DeleteAccountControllerTitle" = "删除帐号"; + +/* Alert message shown before account deletion. */ +"ActionCantBeUndone" = "此操作无法撤消"; + +/* Button title for unlinking account action. */ +"UnlinkAction" = "取消关联"; + +/* Controller title shown for unlinking account action. */ +"UnlinkTitle" = "已关联的帐号"; + +/* Alert title shown before unlinking action. */ +"UnlinkConfirmationTitle" = "要取消帐号关联吗?"; + +/* Alert message shown before unlinking action. */ +"UnlinkConfirmationMessage" = "您将不能再使用您的帐号登录"; + +/* Alert action title shown before unlinking action. */ +"UnlinkConfirmationActionTitle" = "取消帐号关联"; + +/* Alert action message shown before updating email action. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"UpdateEmailAlertMessage" = "要更改与您的帐号关联的电子邮件地址,您需要再次登录。"; + +/* Alert action message shown before confirmation of updating email action. */ +"UpdateEmailVerificationAlertMessage" = "要更改密码,您需要先输入当前的密码。"; + +/* Controller title shown when editing account email. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"EditEmailTitle" = "修改电子邮件地址"; + +/* Controller title shown when editing account name. */ +"EditNameTitle" = "修改名称"; + +/* Alert message shown when adding account password. */ +"AddPasswordAlertMessage" = "要为帐号添加密码,您需要重新登录。"; + +/* Alert message shown when editing account password. */ +"EditPasswordAlertMessage" = "要更改帐号的密码,您需要重新登录。"; + +/* Alert message shown when re-authenticating before editing account password. */ +"ReauthenticateEditPasswordAlertMessage" = "要更改密码,您需要先输入当前的密码。"; + +/* Controller title shown when adding password to account. */ +"AddPasswordTitle" = "添加密码"; + +/* Controller title shown when editing password to account. */ +"EditPasswordTitle" = "更改密码"; + +/* Title of Password/Email provider. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"ProviderTitlePassword" = "电子邮件"; + +/* Title of Google provider */ +"ProviderTitleGoogle" = "Google"; + +/* Title of Facebook provider */ +"ProviderTitleFacebook" = "Facebook"; + +/* Title of Twitter provider */ +"ProviderTitleTwitter" = "Twitter"; + +/* Sign in with provider button label. */ +"SignInWithProvider" = "使用 %@ 帐号登录"; + +/* Placeholder of input cell when user changes name. */ +"PlaceholderEnterName" = "输入您的名称"; + +/* Placeholder of input cell when user changes name. Use short/abbreviated translation for 'email' which is less than 15 chars. */ +"PlaceholderEnterEmail" = "输入您的电子邮件地址"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderEnterPassword" = "输入您的密码"; + +/* Placeholder of secret input cell when user confirms password. */ +"PlaceholderNewPassword" = "新密码"; + +/* Placeholder of secret input cell when user changes password. */ +"PlaceholderChosePassword" = "选择密码"; + +/* Title of forgot password button. */ +"ForgotPasswordTitle" = "登录时遇到问题?"; + +/* Title of confirm email label. */ +"ConfirmEmail" = "确认电子邮件地址"; + +/* Title of successfully signed in label. */ +"SignedIn" = "已登录!"; + +/* Title used in trouble getting email alert view. */ +"TroubleGettingEmailTitle" = "无法收到电子邮件?"; + +/* Alert message displayed when user having trouble getting email. */ +"TroubleGettingEmailMessage" = "尝试以下常见解决方法:\n - 检查电子邮件是否被标记为垃圾邮件或被过滤。\n - 检查互联网连接。\n - 确保没有写错电子邮件地址。\n - 确保收件箱空间充足,且不存在其他与收件箱设置有关的问题。\n 如果上述步骤未能帮助您解决问题,您可以重新发送电子邮件。请注意,重新发送后上一封电子邮件中的链接将失效。"; + +/* Message displayed after email is sent. The placeholder is the email address that the email is sent to. */ +"EmailSentConfirmationMessage" = "系统已将含附加说明的登录电子邮件发送至 %@。请查收电子邮件以完成登录。"; + +/* Message displayed after the email of sign-in link is sent. */ +"SignInEmailSent" = "已发送登录电子邮件"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.h b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.h new file mode 100644 index 00000000..6992da29 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIAuthProvider.h" + +NS_ASSUME_NONNULL_BEGIN + +/** @var kGoogleGamesScope + @brief The OAuth scope string for the "Games" scope. + */ +static NSString *const kGoogleGamesScope = @"https://www.googleapis.com/auth/games"; + +/** @var kGooglePlusMeScope + @brief The OAuth scope string for the "plus.me" scope. + */ +static NSString *const kGooglePlusMeScope = @"https://www.googleapis.com/auth/plus.me"; + +/** @var kGooglePlusMeScope + @brief The OAuth scope string for the user's email scope. + */ +static NSString *const kGoogleUserInfoEmailScope = @"https://www.googleapis.com/auth/userinfo.email"; + +/** @var kGooglePlusMeScope + @brief The OAuth scope string for the basic G+ profile information scope. + */ +static NSString *const kGoogleUserInfoProfileScope = @"https://www.googleapis.com/auth/userinfo.profile"; + +/** @class FUIGoogleAuth + @brief AuthUI components for Google Sign In. + */ +@interface FUIGoogleAuth : NSObject + +/** @property scopes + @brief The scopes to use with Google Sign In. + @remarks Defaults to using email and profile scopes. For a list of all scopes + see https://developers.google.com/identity/protocols/googlescopes + */ +@property(nonatomic, copy, readonly) NSArray *scopes; + +/** @property buttonAlignment + @brief The alignment of the icon and text of the button. + */ +@property(nonatomic, readwrite) FUIButtonAlignment buttonAlignment; + +/** @fn init + @brief Convenience initializer. Calls designated init with default + scopes of "email" and "profile". + */ +- (instancetype)init; + +/** @fn initWithScopes: + @brief Designated initializer. + @param scopes The user account scopes required by the app. A list of possible scopes can be + found at https://developers.google.com/identity/protocols/googlescopes + */ +- (instancetype)initWithScopes:(NSArray *)scopes NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.m b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.m new file mode 100644 index 00000000..d328a94f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.m @@ -0,0 +1,222 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "FUIGoogleAuth.h" + +#import +#import +#import +#import "FUIAuthBaseViewController.h" +#import "FUIAuthErrorUtils.h" +#import "FirebaseAuthUI.h" +#import +#import +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthStrings.h" +#import "FUIAuthUtils.h" + +/** @var kTableName + @brief The name of the strings table to search for localized strings. + */ +static NSString *const kTableName = @"FirebaseGoogleAuthUI"; + +/** @var kBundleName + @brief The name of the bundle to search for resources. + */ +static NSString *const kBundleName = @"FirebaseGoogleAuthUI"; + +/** @var kSignInWithGoogle + @brief The string key for localized button text. + */ +static NSString *const kSignInWithGoogle = @"SignInWithGoogle"; + +@interface FUIGoogleAuth () +@end +@implementation FUIGoogleAuth { + /** @var _presentingViewController + @brief The presenting view controller for interactive sign-in. + */ + UIViewController *_presentingViewController; + + /** @var _pendingSignInCallback + @brief The callback which should be invoked when the sign in flow completes (or is cancelled.) + */ + FUIAuthProviderSignInCompletionBlock _pendingSignInCallback; + + /** @var _email + @brief The email address associated with this account. + */ + NSString *_email; +} + +- (instancetype)init { + return [self initWithScopes:@[kGoogleUserInfoEmailScope, kGoogleUserInfoProfileScope]]; +} + +- (instancetype)initWithScopes:(NSArray *)scopes { + self = [super init]; + if (self) { + _scopes = [scopes copy]; + } + return self; +} + +#pragma mark - FUIAuthProvider + +- (nullable NSString *)providerID { + return FIRGoogleAuthProviderID; +} + +- (nullable NSString *)accessToken { + return [GIDSignIn sharedInstance].currentUser.authentication.accessToken; +} + +- (nullable NSString *)idToken { + return [GIDSignIn sharedInstance].currentUser.authentication.idToken; +} + +- (NSString *)shortName { + return @"Google"; +} + +- (NSString *)signInLabel { + return FUILocalizedStringFromTableInBundle(kSignInWithGoogle, kTableName, kBundleName); +} + +- (UIImage *)icon { + return [FUIAuthUtils imageNamed:@"ic_google" fromBundleNameOrNil:kBundleName]; +} + +- (UIColor *)buttonBackgroundColor { + return [UIColor whiteColor]; +} + +- (UIColor *)buttonTextColor { + return [UIColor colorWithWhite:0 alpha:0.54f]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (void)signInWithEmail:(nullable NSString *)email + presentingViewController:(nullable UIViewController *)presentingViewController + completion:(nullable FUIAuthProviderSignInCompletionBlock)completion { + [self signInWithDefaultValue:email + presentingViewController:presentingViewController + completion:completion]; +} +#pragma clang diagnostic pop + +- (void)signInWithDefaultValue:(nullable NSString *)defaultValue + presentingViewController:(nullable UIViewController *)presentingViewController + completion:(nullable FUIAuthProviderSignInCompletionBlock)completion { + _presentingViewController = presentingViewController; + + GIDSignIn *signIn = [self configuredGoogleSignIn]; + signIn.presentingViewController = presentingViewController; + _pendingSignInCallback = ^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error, + _Nullable FIRAuthResultCallback result, + NSDictionary *_Nullable userInfo) { + signIn.loginHint = nil; + if (completion) { + completion(credential, error, result, nil); + } + }; + + signIn.loginHint = defaultValue; + [signIn signIn]; +} + +- (void)signOut { + GIDSignIn *signIn = [self configuredGoogleSignIn]; + [signIn signOut]; +} + +- (BOOL)handleOpenURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication { + GIDSignIn *signIn = [self configuredGoogleSignIn]; + return [signIn handleURL:URL]; +} + +- (NSString *)email { + return _email; +} + +#pragma mark - GIDSignInDelegate methods + +- (void)signIn:(GIDSignIn *)signIn + didSignInForUser:(GIDGoogleUser *)user + withError:(NSError *)error { + if (error) { + if (error.code == kGIDSignInErrorCodeCanceled) { + [self callbackWithCredential:nil + error:[FUIAuthErrorUtils + userCancelledSignInError] result:nil]; + } else { + NSError *newError = + [FUIAuthErrorUtils providerErrorWithUnderlyingError:error + providerID:FIRGoogleAuthProviderID]; + [self callbackWithCredential:nil error:newError result:nil]; + } + return; + } + _email = user.profile.email; + UIActivityIndicatorView *activityView = + [FUIAuthBaseViewController addActivityIndicator:_presentingViewController.view]; + [activityView startAnimating]; + FIRAuthCredential *credential = + [FIRGoogleAuthProvider credentialWithIDToken:user.authentication.idToken + accessToken:user.authentication.accessToken]; + [self callbackWithCredential:credential error:nil result:^(FIRUser *_Nullable user, + NSError *_Nullable error) { + [activityView stopAnimating]; + [activityView removeFromSuperview]; + }]; +} + +#pragma mark - Helpers + +/** @fn configuredGoogleSignIn + @brief Returns an instance of @c GIDSignIn which is configured to match the configuration + of this instance. + */ +- (GIDSignIn *)configuredGoogleSignIn { + GIDSignIn *signIn = [GIDSignIn sharedInstance]; + signIn.delegate = self; + signIn.shouldFetchBasicProfile = YES; + signIn.clientID = [[FIRApp defaultApp] options].clientID; + signIn.scopes = _scopes; + return signIn; +} + +/** @fn callbackWithCredential:error: + @brief Ends the sign-in flow by cleaning up and calling back with given credential or error. + @param credential The credential to pass back, if any. + @param error The error to pass back, if any. + @param result The result of sign-in operation using provided @c FIRAuthCredential object. + @see @c FIRAuth.signInWithCredential:completion: + */ +- (void)callbackWithCredential:(nullable FIRAuthCredential *)credential + error:(nullable NSError *)error + result:(nullable FIRAuthResultCallback)result { + FUIAuthProviderSignInCompletionBlock callback = _pendingSignInCallback; + _presentingViewController = nil; + _pendingSignInCallback = nil; + if (callback) { + callback(credential, error, result, nil); + } +} + +@end diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FirebaseGoogleAuthUI.h b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FirebaseGoogleAuthUI.h new file mode 100644 index 00000000..7c831f74 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/FirebaseGoogleAuthUI.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@import UIKit; + +//! Project version number for FirebaseGoogleAuthUI. +FOUNDATION_EXPORT double FirebaseGoogleAuthUIVersionNumber; + +//! Project version string for FirebaseGoogleAuthUI. +FOUNDATION_EXPORT const unsigned char FirebaseGoogleAuthUIVersionString[]; + +#import "FUIGoogleAuth.h" diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google.png b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google.png new file mode 100644 index 00000000..4b0e1c00 Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@2x.png b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@2x.png new file mode 100644 index 00000000..62b29c6a Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@2x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@3x.png b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@3x.png new file mode 100644 index 00000000..2a2ac76c Binary files /dev/null and b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@3x.png differ diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ar.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ar.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..4efe2230 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ar.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "تسجيل الدخول عبر Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bg.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bg.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..839b9a15 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bg.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Вход с Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bn.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bn.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..e31fe522 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/bn.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google দিয়ে সাইন-ইন করুন"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ca.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ca.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..63865fea --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ca.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Inicia la sessió amb Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/cs.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/cs.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..42c972b2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/cs.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Přihlaste se účtem Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/da.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/da.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..2db7de8b --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/da.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Log ind med Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-AT.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-AT.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f34ffa78 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-AT.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Über Google anmelden"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-CH.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-CH.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f34ffa78 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de-CH.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Über Google anmelden"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f34ffa78 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/de.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Über Google anmelden"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/el.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/el.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..76a035b4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/el.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Σύνδεση μέσω Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-AU.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-AU.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-AU.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-CA.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-CA.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-CA.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-GB.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-GB.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-GB.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IE.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IE.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IE.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IN.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IN.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IN.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-SG.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-SG.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-SG.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-ZA.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-ZA.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en-ZA.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f8145396 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/en.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Sign in with Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-419.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-419.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-419.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-AR.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-AR.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-AR.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-BO.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-BO.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-BO.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CL.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CL.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CL.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CO.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CO.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CO.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CR.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CR.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CR.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-DO.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-DO.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-DO.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-EC.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-EC.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-EC.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-GT.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-GT.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-GT.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-HN.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-HN.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-HN.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-MX.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-MX.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-MX.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-NI.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-NI.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-NI.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PA.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PA.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PA.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PE.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PE.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PE.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PR.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PR.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PR.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PY.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PY.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PY.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-SV.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-SV.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-SV.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-US.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-US.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-US.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-UY.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-UY.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-UY.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-VE.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-VE.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..87462873 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es-VE.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Acceder con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..0c63fcca --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/es.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Iniciar sesión con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fa.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fa.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..9675abcf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fa.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "ورود به سیستم با Google‎"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fi.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fi.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..3eb0d25c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fi.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Kirjaudu Google-tilillä"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fil.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fil.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..a2df5adf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fil.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Mag-sign in sa Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr-CH.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr-CH.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..890742b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr-CH.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Se connecter avec Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..890742b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/fr.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Se connecter avec Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gsw.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gsw.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f34ffa78 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gsw.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Über Google anmelden"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gu.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gu.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..395c7b2f --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/gu.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google વડે સાઇન ઇન કરો"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/he.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/he.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..a1e7afc2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/he.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "כניסה באמצעות Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hi.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hi.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..bca4cb81 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hi.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google से प्रवेश करें"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hr.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hr.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..733dc1fe --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hr.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Prijava putem Googlea"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hu.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hu.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..6512cffe --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/hu.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Bejelentkezés Google-fiókkal"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/id.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/id.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..01e14638 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/id.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Login dengan Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/it.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/it.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..5e0b7c79 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/it.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Accedi con Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ja.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ja.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f56a07b2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ja.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google でログイン"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/kn.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/kn.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..b9e52fda --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/kn.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google ಮೂಲಕ ಸೈನ್ ಇನ್ ಮಾಡಿ"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ko.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ko.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..bb872f3e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ko.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google 계정으로 로그인"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ln.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ln.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..890742b1 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ln.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Se connecter avec Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lt.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lt.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..7743afbf --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lt.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Prisijungti per „Google“"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lv.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lv.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..079aad36 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/lv.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Pierakstīties ar Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/mr.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/mr.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..22347ebd --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/mr.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Googleने साइन इन करा"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ms.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ms.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..dfedb53c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ms.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Log masuk dengan Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nb.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nb.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..e4f3243c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nb.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Logg på med Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nl.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nl.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..42bfe001 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nl.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Inloggen met Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nn-NO.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nn-NO.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..e4f3243c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/nn-NO.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Logg på med Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pl.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pl.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..149abf6a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pl.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Zaloguj się przez Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-BR.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-BR.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..0fa304fb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-BR.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Fazer login com o Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-PT.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-PT.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..2ca321d9 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-PT.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Iniciar sessão com o Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..0fa304fb --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/pt.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Fazer login com o Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ro.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ro.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..e5d25a7e --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ro.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Conectați-vă cu Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ru.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ru.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..dba30be2 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ru.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Войти через аккаунт Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sk.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sk.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..854dad1c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sk.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Prihlásiť sa cez Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sl.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sl.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..40bfec3c --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sl.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Prijava z Google Računom"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr-Latn.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr-Latn.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..65a17604 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr-Latn.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Prijavi me pomoću Google-a"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..b3cde991 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sr.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Пријави ме помоћу Google-а"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sv.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sv.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..2292766a --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/sv.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Logga in med Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ta.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ta.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..4affb137 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ta.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google மூலம் உள்நுழைக"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/th.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/th.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..a0713d48 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/th.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "ลงชื่อเข้าใช้ด้วย Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/tr.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/tr.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..a715b653 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/tr.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google ile oturum aç"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/uk.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/uk.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..f1a8af11 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/uk.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Увійти через Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ur.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ur.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..5d012107 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/ur.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Google کے ساتھ سائن ان کریں"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/vi.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/vi.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..8a4d2921 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/vi.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "Đăng nhập bằng Google"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hans.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hans.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..25c7aef4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hans.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "使用 Google 帐号登录"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant-TW.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant-TW.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..26e20b9d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant-TW.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "使用 Google 帳戶登入"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..26e20b9d --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "使用 Google 帳戶登入"; diff --git a/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh.lproj/FirebaseGoogleAuthUI.strings b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh.lproj/FirebaseGoogleAuthUI.strings new file mode 100644 index 00000000..25c7aef4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/GoogleAuth/FirebaseGoogleAuthUI/Strings/zh.lproj/FirebaseGoogleAuthUI.strings @@ -0,0 +1,2 @@ +/* The text of the button used to sign-in with Google. */ +"SignInWithGoogle" = "使用 Google 帐号登录"; diff --git a/MyExperiences copy/Pods/FirebaseUI/LICENSE b/MyExperiences copy/Pods/FirebaseUI/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/FirebaseUI/README.md b/MyExperiences copy/Pods/FirebaseUI/README.md new file mode 100644 index 00000000..e059d2f4 --- /dev/null +++ b/MyExperiences copy/Pods/FirebaseUI/README.md @@ -0,0 +1,154 @@ +# FirebaseUI for iOS — UI Bindings for Firebase [![Build Status](https://travis-ci.org/firebase/FirebaseUI-iOS.svg?branch=master)](https://travis-ci.org/firebase/FirebaseUI-iOS) + +FirebaseUI is an open-source library for iOS that allows you to quickly connect common UI elements to the [Firebase](https://firebase.google.com?utm_source=FirebaseUI-iOS) database for data storage, allowing views to be updated in realtime as they change, and providing simple interfaces for common tasks like displaying lists or collections of items. + +Additionally, FirebaseUI simplifies Firebase authentication by providing easy to use auth methods that integrate with common identity providers like Facebook, Twitter, and Google as well as allowing developers to use a built in headful UI for ease of development. + +FirebaseUI clients are also available for [Android](https://github.com/firebase/FirebaseUI-Android) and [web](https://github.com/firebase/firebaseui-web). + +![](https://raw.githubusercontent.com/firebase/FirebaseUI-iOS/master/samples/demo.gif) + +## Installing FirebaseUI for iOS + +FirebaseUI supports iOS 8.0+ and Xcode 11+. We recommend using [CocoaPods](https://cocoapods.org/pods/FirebaseUI), add +the following to your `Podfile`: + +```ruby +pod 'FirebaseUI', '~> 8.0' # Pull in all Firebase UI features +``` + +If you don't want to use all of FirebaseUI, there are multiple subspecs which can selectively install subsets of the full feature set: + +```ruby +# Only pull in Firestore features +pod 'FirebaseUI/Firestore', '~> 8.0' + +# Only pull in Database features +pod 'FirebaseUI/Database', '~> 8.0' + +# Only pull in Storage features +pod 'FirebaseUI/Storage', '~> 8.0' + +# Only pull in Auth features +pod 'FirebaseUI/Auth', '~> 8.0' + +# Only pull in Facebook login features +pod 'FirebaseUI/Facebook', '~> 8.0' + +# Only pull in Google login features +pod 'FirebaseUI/Google', '~> 8.0' + +# Only pull in Phone Auth login features +pod 'FirebaseUI/Phone', '~> 8.0' +``` + +If you're including FirebaseUI in a Swift project, make sure you also have: + +```ruby +platform :ios, '9.0' +use_frameworks! +``` + +Otherwise, you can include the FirebaseUI Xcode project from this repo in +your project. You also need to +[add the Firebase framework](https://firebase.google.com/docs/ios/setup) +to your project. + +## Documentation + +The READMEs for components of FirebaseUI can be found in their respective +project folders. + +- [Auth](Auth/README.md) +- [PhoneAuth](PhoneAuth/README.md) +- [Database](Database/README.md) +- [Firestore](Firestore/README.md) +- [Storage](Storage/README.md) + +## Local Setup + +If you'd like to contribute to FirebaseUI for iOS, you'll need to run the +following commands to get your environment set up: + +```bash +$ git clone https://github.com/firebase/FirebaseUI-iOS.git +$ cd FirebaseUI-iOS +$ cd Auth # or PhoneAuth, Database, etc +$ pod install +``` + +Alternatively you can use `pod try FirebaseUI` to install the Objective-C or Swift sample projects. + +## Sample Project Configuration + +You'll have to configure your Xcode project in order to run the samples. + +1. Your Xcode project should contain a `GoogleService-Info.plist`, downloaded from [Firebase console](https://console.firebase.google.com) when you add your app to a Firebase project.
+Copy the `GoogleService-Info.plist` into the sample project folder (`samples/obj-c/GoogleService-Info.plist` or `samples/swift/GoogleService-Info.plist`). + +1. Update URL Types.
+Go to `Project Settings -> Info tab -> Url Types` and update values for: + + `REVERSED_CLIENT_ID` (get value from `GoogleService-Info.plist`) + + `fb{your-app-id}` (put Facebook App Id) + +1. Update `Info.plist` with Facebook configuration values + + `FacebookAppID -> {your-app-id}` (put Facebook App Id) + +1. Enable Keychain Sharing.
+Facebook SDK requires keychain sharing.
+This can be done here: `Project Settings -> Capabilities -> KeyChain Sharing -> ON` + +1. Don't forget to configure your Firebase App Database using [Firebase console](https://console.firebase.google.com).
+Database should contain appropriate read/write permissions and folders (`objc_demo-chat` and `swift_demo-chat` respectively) + +1. In Order to use `Phone Auth` provider you should [Configure Push Notifications](#configure-apple-push-notifications) + +#### Configure Apple Push Notifications + +##### Enable silent push notifications in Xcode + + * `Push Notification` - Under `Capabilities` tab in your app target choose `Push Notifications` and put the switch to the `On` position. + * `Background Mode` - Under `Capabilities` tab in your app target choose `Background Modes` put the switch to the `On` position. In the list of available modes select `Background fetch` and `Remote notifications` (If available). + +##### Upload APNS Certificate to Firebase + +1. Create your `Provisioning APNS SSL Certificates` by following the steps on the following link. +https://firebase.google.com/docs/cloud-messaging/ios/certs + +1. Upload your `APNS Certificate` to Firebase: + + Inside your project in the Firebase console, select the gear icon, select `Project Settings`, and then select the `Cloud Messaging` tab. + + Select the `Upload Certificate` button for your development certificate, your production certificate, or both. At least one is required. + + For each certificate, select the `.p12 file`, and provide the password, if any. Make sure the `bundle ID` for this certificate matches the `bundle ID` of your app. Select `Save`. + +## Contributing to FirebaseUI + +### Contributor License Agreements + +We'd love to accept your sample apps and patches! Before we can take them, we +have to jump a couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + + * If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an [individual CLA] + (https://developers.google.com/open-source/cla/individual). + * If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a [corporate CLA] + (https://developers.google.com/open-source/cla/corporate). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +### Contribution Process + +1. Submit an issue describing your proposed change to the repo in question. +1. The repo owner will respond to your issue promptly. +1. If your proposed change is accepted, and you haven't already done so, sign a + Contributor License Agreement (see details above). +1. Fork the desired repo, develop and test your code changes. +1. Ensure that your code adheres to the existing style of the library to which + you are contributing. +1. Ensure that your code has an appropriate set of unit tests which all pass. +1. Submit a pull request diff --git a/MyExperiences copy/Pods/GTMAppAuth/LICENSE b/MyExperiences copy/Pods/GTMAppAuth/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/GTMAppAuth/README.md b/MyExperiences copy/Pods/GTMAppAuth/README.md new file mode 100644 index 00000000..e2c02fd0 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/README.md @@ -0,0 +1,385 @@ +# GTMAppAuth for iOS and macOS + +GTMAppAuth enables you to use [AppAuth](http://openid.github.io/AppAuth-iOS) +with the +[Google Toolbox for Mac - Session Fetcher](https://github.com/google/gtm-session-fetcher) +and +[Google APIs Client Library for Objective-C For REST](https://github.com/google/google-api-objectivec-client-for-rest) +libraries by providing an implementation of `GTMFetcherAuthorizationProtocol` +for authorizing requests with AppAuth. + +GTMAppAuth is an alternative authorizer to GTMOAuth2. The key differentiator is +the use of the user's default browser for the authorization, which is more +secure, more usable (the user's session can be reused) and follows modern OAuth +[best practices for native apps](https://tools.ietf.org/html/draft-ietf-oauth-native-apps). +Compatibility methods for GTMOAuth2 are offered allowing you to migrate +from GTMOAuth2 to GTMAppAuth preserving previously serialized authorizations +(so users shouldn't need to re-authenticate). + +## Setup + +If you use [CocoaPods](https://guides.cocoapods.org/using/getting-started.html), +simply add: + + pod 'GTMAppAuth' + +To your `Podfile` and run `pod install`. + +## Usage + +### Configuration + +To configure GTMAppAuth with the OAuth endpoints for Google, you can use the +convenience method: + +```objc +OIDServiceConfiguration *configuration = + [GTMAppAuthFetcherAuthorization configurationForGoogle]; +``` + +Alternatively, you can configure GTMAppAuth by specifying the endpoints +directly: + +```objc +NSURL *authorizationEndpoint = + [NSURL URLWithString:@"https://accounts.google.com/o/oauth2/v2/auth"]; +NSURL *tokenEndpoint = + [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"]; + +OIDServiceConfiguration *configuration = + [[OIDServiceConfiguration alloc] + initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint]; + +// perform the auth request... +``` + +Or through discovery: + +```objc +NSURL *issuer = [NSURL URLWithString:@"https://accounts.google.com"]; + +[OIDAuthorizationService discoverServiceConfigurationForIssuer:issuer + completion:^(OIDServiceConfiguration *_Nullable configuration, + NSError *_Nullable error) { + if (!configuration) { + NSLog(@"Error retrieving discovery document: %@", + [error localizedDescription]); + return; + } + + // perform the auth request... +}]; +``` + +### Authorizing + +First, you need to have a way for your UIApplicationDelegate to continue the +authorization flow session from the incoming redirect URI. Typically you could +store the in-progress OIDAuthorizationFlowSession instance in a property: + +```objc +// property of the app's UIApplicationDelegate +@property(nonatomic, nullable) + id currentAuthorizationFlow; +``` + +And in a location accessible by all controllers that need authorization, a +property to store the authorization state: + +```objc +// property of the containing class +@property(nonatomic, nullable) GTMAppAuthFetcherAuthorization *authorization; +``` + +Then, initiate the authorization request. By using the +`authStateByPresentingAuthorizationRequest` method, the OAuth token +exchange will be performed automatically, and everything will be protected with +PKCE (if the server supports it). + +```objc +// builds authentication request +OIDAuthorizationRequest *request = + [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration + clientId:kClientID + clientSecret:kClientSecret + scopes:@[OIDScopeOpenID, OIDScopeProfile] + redirectURL:redirectURI + responseType:OIDResponseTypeCode + additionalParameters:nil]; +// performs authentication request +self.appDelegate.currentAuthorizationFlow = + [OIDAuthState authStateByPresentingAuthorizationRequest:request + callback:^(OIDAuthState *_Nullable authState, + NSError *_Nullable error) { + if (authState) { + // Creates the GTMAppAuthFetcherAuthorization from the OIDAuthState. + GTMAppAuthFetcherAuthorization *authorization = + [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState]; + + self.authorization = authorization; + NSLog(@"Got authorization tokens. Access token: %@", + authState.lastTokenResponse.accessToken); + } else { + NSLog(@"Authorization error: %@", [error localizedDescription]); + self.authorization = nil; + } +}]; +``` + +### Handling the Redirect + +The authorization response URL is returned to the app via the platform-specific +application delegate method, so you need to pipe this through to the current +authorization session (created in the previous session). + +#### macOS Custom URI Scheme Redirect Example + +```objc +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Other app initialization code ... + + // Register for GetURL events. + NSAppleEventManager *appleEventManager = + [NSAppleEventManager sharedAppleEventManager]; + [appleEventManager setEventHandler:self + andSelector:@selector(handleGetURLEvent:withReplyEvent:) + forEventClass:kInternetEventClass + andEventID:kAEGetURL]; +} + +- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event + withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + NSString *URLString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; + NSURL *URL = [NSURL URLWithString:URLString]; + [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:URL]; +} +``` + +#### iOS Custom URI Scheme Redirect Example + +```objc +- (BOOL)application:(UIApplication *)app + openURL:(NSURL *)url + options:(NSDictionary *)options { + // Sends the URL to the current authorization flow (if any) which will + // process it if it relates to an authorization response. + if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) { + _currentAuthorizationFlow = nil; + return YES; + } + + // Your additional URL handling (if any) goes here. + + return NO; +} +``` + +### Making API Calls + +The goal of GTMAppAuth is to enable you to authorize HTTP requests with fresh +tokens following the Session Fetcher pattern, which you can do like so: + +```objc +// Creates a GTMSessionFetcherService with the authorization. +// Normally you would save this service object and re-use it for all REST API calls. +GTMSessionFetcherService *fetcherService = [[GTMSessionFetcherService alloc] init]; +fetcherService.authorizer = self.authorization; + +// Creates a fetcher for the API call. +NSURL *userinfoEndpoint = [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v3/userinfo"]; +GTMSessionFetcher *fetcher = [fetcherService fetcherWithURL:userinfoEndpoint]; +[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + // Checks for an error. + if (error) { + // OIDOAuthTokenErrorDomain indicates an issue with the authorization. + if ([error.domain isEqual:OIDOAuthTokenErrorDomain]) { + self.authorization = nil; + NSLog(@"Authorization error during token refresh, clearing state. %@", + error); + // Other errors are assumed transient. + } else { + NSLog(@"Transient error during token refresh. %@", error); + } + return; + } + + // Parses the JSON response. + NSError *jsonError = nil; + id jsonDictionaryOrArray = + [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError]; + + // JSON error. + if (jsonError) { + NSLog(@"JSON decoding error %@", jsonError); + return; + } + + // Success response! + NSLog(@"Success: %@", jsonDictionaryOrArray); +}]; +``` + +### Serialization + +You can easily serialize `GTMAppAuthFetcherAuthorization` objects using the +included Keychain category. + +```objc +// Serialize to Keychain +[GTMAppAuthFetcherAuthorization saveAuthorization:_authorization + toKeychainForName:kGTMAppAuthExampleAuthorizerKey]; + +// Deserialize from Keychain +GTMAppAuthFetcherAuthorization* authorization = + [GTMAppAuthFetcherAuthorization authorizationFromKeychainForName:kGTMAppAuthExampleAuthorizerKey]; + +// Remove from Keychain +[GTMAppAuthFetcherAuthorization + removeAuthorizationFromKeychainForName:kGTMAppAuthExampleAuthorizerKey]; +``` + +### GTMOAuth2-compatible Serialization + +To assist the migration from GTMOAuth2 to GTMAppAuth, GTMOAuth2-compatible +serialization methods are provided in `GTMOAuth2KeychainCompatibility`. + +```objc +// Deserialize from Keychain +GTMAppAuthFetcherAuthorization *auth = + [GTMOAuth2KeychainCompatibility authForGoogleFromKeychainForName:kKeychainItemName + clientID:clientID + clientSecret:clientSecret]; + +// Remove from Keychain +[GTMOAuth2KeychainCompatibility removeAuthFromKeychainForName:kKeychainItemName]; +``` + +You can also serialize to GTMOAuth2 format, though this is discouraged (you +should serialize in GTMAppAuth format as described above). + +```objc +// Serialize to Keychain +[GTMOAuth2KeychainCompatibility saveAuthToKeychainForName:kKeychainItemName + authentication:authorization]; +``` + +## Included Samples + +Try out one of the included sample apps under [Examples](Examples). In the +apps folder run `pod install`, then open the resulting `xcworkspace` file. + +Be sure to follow the instructions in +[Example-iOS/README.md](Examples/Example-iOS/README.md) or +[Example-macOS/README.md](Examples/Example-macOS/README.md) to configure +your own OAuth client ID for use with the example. + +## Differences with GTMOAuth2 + +### Authorization Method + +GTMAppAuth uses the browser to present the authorization request, while +GTMOAuth2 uses an embedded web-view. Migrating to GTMAppAuth will require you +to change how you authorize the user. Follow the instructions above to get the +authorization. You can then create a `GTMAppAuthFetcherAuthorization` object +with the `initWithAuthState:authState` initializer. + +Once you have the `GTMAppAuthFetcherAuthorization` you can continue to make REST +calls as before. + +### Error Handling + +GTMAppAuth's error handling is also different. There are no notifications, +instead you need to inspect NSError in the callback. If the error domain is +`OIDOAuthTokenErrorDomain`, it indicates an authorization error, you should +clear your authorization state and consider prompting the user to authorize +again. Other errors are generally considered transient, meaning that you should +retry the request after a delay. + +### Serialization + +The serialization format is different between GTMOAuth2 and GTMAppAuth, though +we have methods to help you migrate from one to the other without losing any +data. + +## Migrating from GTMOAuth2 + +### OAuth Client Registration + +Typically, GTMOAuth2 clients are registered with Google as type "Other". This is +correct for macOS, but on iOS clients should be registered with the type "iOS". + +If you're migrating an iOS client, in the *same project as your existing client*, +[register a new iOS client](https://console.developers.google.com/apis/credentials?project=_) +to be used with GTMAppAuth. + +### Changing your Authorization Flows + +Both GTMOAuth2 and GTMAppAuth support the `GTMFetcherAuthorizationProtocol` +allowing you to use the authorization with the session fetcher. Where you +previously had a property like `GTMOAuth2Authentication *authorization` change the +type to reference the protocol instead, i.e.: +`id authorization`. This allows you to switch +the authorization implementation under the hood to GTMAppAuth. + +Then, follow the instructions above to replace authorization request +(where you ask the user to grant access) with the GTMAppAuth approach. If you +created a new OAuth client, use that for these requests. + +### Serialization & Migrating Existing Grants + +GTMAppAuth has a new data format and APIs for serialization. Unlike +GTMOAuth2, GTMAppAuth serializes the configuration and history of the +authorization, including the client id, and a record of the authorization +request that resulted in the authorization grant. + +The client ID used for GTMAppAuth is [different](#oauth-client-registration) to +the one used for GTMOAuth2. In order to keep track of the different client ids +used for new and old grants, it's recommended to migrate to the new +serialization format, which will store that for you. +[GTMOAuth2-compatible serialization](#gtmoauth2-compatible-serialization) is +also offered, but not fully supported. + +Change how you serialize your `authorization` object using the new methods +using the following example. + +```objc +// Serialize to Keychain +[GTMAppAuthFetcherAuthorization saveAuthorization:(GTMAppAuthFetcherAuthorization *)authorization + toKeychainForName:kNewKeychainName]; +``` + +Be sure to use a *new* name for the keychain. Don't reuse your old one! + +For deserializing, we can preserve all existing grants (so users who authorized +your app in GTMOAuth2 don't have to authorize it again). Remember that when +deserializing the *old* data you need to use your *old* keychain name, and +the old client id and client secret (if those changed), and that when +serializing to the *new* format, use the *new* keychain name. +Once again, pay particular care to use the old details when deserializing the +GTMOAuth2 keychain, and the new details for all other GTMAppAuth calls. + +Keychain migration example: + +```objc +// Attempt to deserialize from Keychain in GTMAppAuth format. +id authorization = + [GTMAppAuthFetcherAuthorization authorizationFromKeychainForName:kNewKeychainName]; + +// If no data found in the new format, try to deserialize data from GTMOAuth2 +if (!authorization) { + // Tries to load the data serialized by GTMOAuth2 using old keychain name. + // If you created a new client id, be sure to use the *previous* client id and secret here. + authorization = + [GTMOAuth2KeychainCompatibility authForGoogleFromKeychainForName:kPreviousKeychainName + clientID:kPreviousClientID + clientSecret:kPreviousClientSecret]; + if (authorization) { + // Remove previously stored GTMOAuth2-formatted data. + [GTMOAuth2KeychainCompatibility removeAuthFromKeychainForName:kPreviousKeychainName]; + // Serialize to Keychain in GTMAppAuth format. + [GTMAppAuthFetcherAuthorization saveAuthorization:(GTMAppAuthFetcherAuthorization *)authorization + toKeychainForName:kNewKeychainName]; + } +} +``` diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuth.h b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuth.h new file mode 100644 index 00000000..ecbdad60 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuth.h @@ -0,0 +1,30 @@ +/*! @file GTMAppAuth.h + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMAppAuthFetcherAuthorization.h" +#import "GTMAppAuthFetcherAuthorization+Keychain.h" + +#if TARGET_OS_TV +#elif TARGET_OS_WATCH +#elif TARGET_OS_IOS +#import "GTMOAuth2KeychainCompatibility.h" +#elif TARGET_OS_MAC +#import "GTMOAuth2KeychainCompatibility.h" +#else +#warn "Platform Undefined" +#endif diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.h b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.h new file mode 100644 index 00000000..f0b9ffeb --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.h @@ -0,0 +1,52 @@ +/*! @file GTMAppAuthFetcherAuthorization+Keychain.h + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMAppAuthFetcherAuthorization.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Category to support serialization and deserialization of + @c GTMAppAuthFetcherAuthorization in the format used by GTMAppAuth. + */ +@interface GTMAppAuthFetcherAuthorization (Keychain) + +/*! @brief Attempts to create a @c GTMAppAuthFetcherAuthorization from data stored in the keychain + in GTMAppAuth format. + @param keychainItemName The keychain name. + @return A @c GTMAppAuthFetcherAuthorization object, or nil. + */ ++ (nullable GTMAppAuthFetcherAuthorization *) + authorizationFromKeychainForName:(NSString *)keychainItemName; + +/*! @brief Removes a stored authorization state. + @param keychainItemName The keychain name. + @return YES the tokens were removed successfully (or didn't exist). + */ ++ (BOOL)removeAuthorizationFromKeychainForName:(NSString *)keychainItemName; + +/*! @brief Saves the authorization state to the keychain, in GTMAppAuth format. + @param auth The authorization to save. + @param keychainItemName The keychain name. + @return YES when the state was saved successfully. + */ ++ (BOOL)saveAuthorization:(GTMAppAuthFetcherAuthorization *)auth + toKeychainForName:(NSString *)keychainItemName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.m b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.m new file mode 100644 index 00000000..e4910a81 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization+Keychain.m @@ -0,0 +1,46 @@ +/*! @file GTMAppAuthFetcherAuthorization+Keychain.m + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMAppAuthFetcherAuthorization+Keychain.h" + +#import "GTMKeychain.h" + +@implementation GTMAppAuthFetcherAuthorization (Keychain) + ++ (GTMAppAuthFetcherAuthorization *)authorizationFromKeychainForName:(NSString *)keychainItemName { + NSData *passwordData = [GTMKeychain passwordDataFromKeychainForName:keychainItemName]; + if (!passwordData) { + return nil; + } + GTMAppAuthFetcherAuthorization *authorization = (GTMAppAuthFetcherAuthorization *) + [NSKeyedUnarchiver unarchiveObjectWithData:passwordData]; + return authorization; +} + ++ (BOOL)removeAuthorizationFromKeychainForName:(NSString *)keychainItemName { + return [GTMKeychain removePasswordFromKeychainForName:keychainItemName]; +} + ++ (BOOL)saveAuthorization:(GTMAppAuthFetcherAuthorization *)auth + toKeychainForName:(NSString *)keychainItemName { + NSData *authorizationData = [NSKeyedArchiver archivedDataWithRootObject:auth]; + return [GTMKeychain savePasswordDataToKeychainForName:keychainItemName + passwordData:authorizationData]; +} + +@end diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.h b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.h new file mode 100644 index 00000000..248223c8 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.h @@ -0,0 +1,153 @@ +/*! @file GTMAppAuthFetcherAuthorization.h + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GTMAPPAUTH_USER_IMPORTS +#import +#else // GTMAPPAUTH_USER_IMPORTS +#import "GTMSessionFetcher.h" +#endif // GTMAPPAUTH_USER_IMPORTS + +@class OIDAuthState; +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief The userInfo key for the @c NSURLRequest. + */ +extern NSString *const GTMAppAuthFetcherAuthorizationErrorRequestKey; + +/*! @brief The error domain for errors specific to the session fetcher authorization. + */ +extern NSString *const GTMAppAuthFetcherAuthorizationErrorDomain; + +/*! @brief Enum of all possible error codes in the @c ::GTMAppAuthFetcherAuthorizationErrorDomain + domain. + @discussion Note that these are GTMAppAuth-specific errors. When AppAuth errors are encountered, + those are returned instead. + */ +typedef NS_ENUM(NSInteger, GTMAppAuthFetcherAuthorizationError) { + GTMAppAuthFetcherAuthorizationErrorUnauthorizableRequest = -1004 +}; + +typedef void (^GTMAppAuthFetcherAuthorizationCompletion)(NSError *_Nullable error); + +@class GTMAppAuthFetcherAuthorization; + +/*! @protocol GTMAppAuthFetcherAuthorizationTokenRefreshDelegate + @brief Delegate of the GTMAppAuthFetcherAuthorization used to supply additional parameters on + token refresh. + */ +@protocol GTMAppAuthFetcherAuthorizationTokenRefreshDelegate + +/*! @brief Called before a token refresh request is performed. + @param authorization The @c GTMFetcherAuthorization performing the token refresh. + @return A dictionary of parameters to be added to the token refresh request. + */ +- (nullable NSDictionary *)additionalRefreshParameters: + (GTMAppAuthFetcherAuthorization *)authorization; + +@end + +/*! @brief An implementation of the @c GTMFetcherAuthorizationProtocol protocol for the AppAuth + library. + @discussion Enables you to use AppAuth with the GTM Session Fetcher library. + */ +@interface GTMAppAuthFetcherAuthorization : NSObject + +/*! @brief The AppAuth authentication state. + */ +@property(nonatomic, readonly) OIDAuthState *authState; + +/*! @brief Service identifier, for example "Google"; not used for authentication. + @discussion The provider name is just for allowing stored authorization to be associated + with the authorizing service. + */ +@property(nullable, nonatomic, readonly) NSString *serviceProvider; + +/*! @brief User ID from the ID Token. + * @discussion Note: Never send this value to your backend as an authentication token, rather send + * an ID Token and validate it. + */ +@property(nullable, nonatomic, readonly) NSString *userID; + +/*! @brief Email verified status; not used for authentication. + @discussion The verified string can be checked with -boolValue. If the result is false, then + the email address is listed with the account on the server, but the address has not been + confirmed as belonging to the owner of the account. + */ +@property(nullable, nonatomic, readonly) NSString *userEmailIsVerified; + +@property(nullable, nonatomic, weak) id + tokenRefreshDelegate; + +/*! @brief Creates a new @c GTMAppAuthFetcherAuthorization using the given @c OIDAuthState from + AppAuth. + @param authState The authorization state. + */ +- (instancetype)initWithAuthState:(OIDAuthState *)authState; + +/*! @brief Creates a new @c GTMAppAuthFetcherAuthorization using the given @c OIDAuthState from + AppAuth. + @param authState The authorization state. + @param serviceProvider An optional string to describe the service. + @param userID An optional string of the user ID. + @param userEmail An optional string of the user's email address. + @param userEmailIsVerified An optional string representation of a boolean to indicate that the + email address has been verified. Pass @"true" for @c YES, or @"false" for @c NO. + @discussion Designated initializer. + */ +- (instancetype)initWithAuthState:(OIDAuthState *)authState + serviceProvider:(nullable NSString *)serviceProvider + userID:(nullable NSString *)userID + userEmail:(nullable NSString *)userEmail + userEmailIsVerified:(nullable NSString *)userEmailIsVerified + NS_DESIGNATED_INITIALIZER; + +#if !GTM_APPAUTH_SKIP_GOOGLE_SUPPORT +/*! @brief Convenience method to return an @c OIDServiceConfiguration for Google. + @return A @c OIDServiceConfiguration object setup with Google OAuth endpoints. + */ ++ (OIDServiceConfiguration *)configurationForGoogle; +#endif // !GTM_APPAUTH_SKIP_GOOGLE_SUPPORT + +/*! @brief Adds an authorization header to the given request, using the authorization state. + Refreshes the access token if needed. + @param request The request to authorize. + @param handler The block that is called after authorizing the request is attempted. If @c error + is non-nil, the authorization failed. Errors in the domain @c ::OIDOAuthTokenErrorDomain + indicate that the authorization itself is invalid, and will need to be re-obtained from the + user. Errors in the @c GTMAppAuthFetcherAuthorizationErrorDomain indicate another + unrecoverable errors. Errors in other domains may indicate a transitive error condition such + as a network error, and typically you do not need to reauthenticate the user on such errors. + @discussion The completion handler is scheduled on the main thread, unless the @c callbackQueue + property is set on the @c fetcherService in which case the handler is scheduled on that + queue. + */ +- (void)authorizeRequest:(nullable NSMutableURLRequest *)request + completionHandler:(GTMAppAuthFetcherAuthorizationCompletion)handler; + +/*! @brief Returns YES if the authorization state is currently valid. + @discussion Note that this doesn't guarantee that a request will get a valid authorization, as + the authorization state could become invalid on on the next token refresh. + */ +- (BOOL)canAuthorize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.m b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.m new file mode 100644 index 00000000..988a87b3 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMAppAuthFetcherAuthorization.m @@ -0,0 +1,492 @@ +/*! @file GTMAppAuthFetcherAuthorization.m + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMAppAuthFetcherAuthorization.h" + +#ifndef GTMAPPAUTH_USER_IMPORTS +#import +#else // GTMAPPAUTH_USER_IMPORTS +#import "AppAuthCore.h" +#endif // GTMAPPAUTH_USER_IMPORTS + +#define GTMOAuth2AssertValidSelector GTMBridgeAssertValidSelector + +/*! @brief Provides a template implementation for init-family methods which have been marked as + NS_UNAVILABLE. Stops the compiler from giving a warning when it's the super class' + designated initializer, and gives callers useful feedback telling them what the + new designated initializer is. + @remarks Takes a SEL as a parameter instead of a string so that we get compiler warnings if the + designated initializer's signature changes. + @param designatedInitializer A SEL referencing the designated initializer. + */ +#define GTM_UNAVAILABLE_USE_INITIALIZER(designatedInitializer) { \ + NSString *reason = [NSString stringWithFormat:@"Called: %@\nDesignated Initializer:%@", \ + NSStringFromSelector(_cmd), \ + NSStringFromSelector(designatedInitializer)]; \ + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." \ + reason:reason \ + userInfo:nil]; \ +} + +/*! @brief Key used to encode the @c authState property for @c NSSecureCoding. + */ +static NSString *const kAuthStateKey = @"authState"; + +/*! @brief Key used to encode the @c serviceProvider property for @c NSSecureCoding. + */ +static NSString *const kServiceProviderKey = @"serviceProvider"; + +/*! @brief Key used to encode the @c userID property for @c NSSecureCoding. + */ +static NSString *const kUserIDKey = @"userID"; + +/*! @brief Key used to encode the @c userEmail property for @c NSSecureCoding. + */ +static NSString *const kUserEmailKey = @"userEmail"; + +/*! @brief Key used to encode the @c userEmailIsVerified property for @c NSSecureCoding. + */ +static NSString *const kUserEmailIsVerifiedKey = @"userEmailIsVerified"; + +NSString *const GTMAppAuthFetcherAuthorizationErrorDomain = + @"kGTMAppAuthFetcherAuthorizationErrorDomain"; +NSString *const GTMAppAuthFetcherAuthorizationErrorRequestKey = @"request"; + +/*! @brief Internal wrapper class for requests needing authorization and their callbacks. + @discusssion Used to abstract away the detail of whether a callback or block is used. + */ +@interface GTMAppAuthFetcherAuthorizationArgs : NSObject + +/*! @brief The request to authorize. + * @discussion Not copied, as we are mutating the request. + */ +@property (nonatomic, strong) NSMutableURLRequest *request; + +/*! @brief The delegate on which @c selector is called on completion. + */ +@property (nonatomic, weak) id delegate; + +/*! @brief The selector called on the @c delegate object on completion. + */ +@property (nonatomic) SEL selector; + +/*! @brief The completion block when the block option was used. + */ +@property (nonatomic, strong) GTMAppAuthFetcherAuthorizationCompletion completionHandler; + +/*! @brief The error that happened during token refresh (if any). + */ +@property (nonatomic, strong) NSError *error; + ++ (GTMAppAuthFetcherAuthorizationArgs *)argsWithRequest:(NSMutableURLRequest *)req + delegate:(id)delegate + selector:(SEL)selector + completionHandler:(GTMAppAuthFetcherAuthorizationCompletion)completionHandler; + +@end + +@implementation GTMAppAuthFetcherAuthorizationArgs + +@synthesize request = _request; +@synthesize delegate = _delegate; +@synthesize selector = _selector; +@synthesize completionHandler = _completionHandler; +@synthesize error = _error; + ++ (GTMAppAuthFetcherAuthorizationArgs *)argsWithRequest:(NSMutableURLRequest *)req + delegate:(id)delegate + selector:(SEL)selector + completionHandler:(GTMAppAuthFetcherAuthorizationCompletion)completionHandler { + GTMAppAuthFetcherAuthorizationArgs *obj; + obj = [[GTMAppAuthFetcherAuthorizationArgs alloc] init]; + obj.request = req; + obj.delegate = delegate; + obj.selector = selector; + obj.completionHandler = completionHandler; + return obj; +} + +@end + +@implementation GTMAppAuthFetcherAuthorization { + /*! @brief Array of requests pending authorization headers. + */ + NSMutableArray *_authorizationQueue; +} + +@synthesize authState = _authState; +@synthesize serviceProvider = _serviceProvider; +@synthesize userID = _userID; +@synthesize userEmailIsVerified = _userEmailIsVerified; + +// GTMFetcherAuthorizationProtocol doesn't specify atomic/nonatomic for these properties. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wimplicit-atomic-properties" +@synthesize userEmail = _userEmail; +@synthesize shouldAuthorizeAllRequests = _shouldAuthorizeAllRequests; +@synthesize fetcherService = _fetcherService; +#pragma clang diagnostic pop + +#pragma mark - Initializers + +// Ignore warning about not calling the designated initializer. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)init + GTM_UNAVAILABLE_USE_INITIALIZER(@selector(initWithAuthState:)); +#pragma clang diagnostic pop + +- (instancetype)initWithAuthState:(OIDAuthState *)authState { + return [self initWithAuthState:authState + serviceProvider:nil + userID:nil + userEmail:nil + userEmailIsVerified:nil]; +} + +- (instancetype)initWithAuthState:(OIDAuthState *)authState + serviceProvider:(nullable NSString *)serviceProvider + userID:(nullable NSString *)userID + userEmail:(nullable NSString *)userEmail + userEmailIsVerified:(nullable NSString *)userEmailIsVerified { + self = [super init]; + if (self) { + _authState = authState; + _authorizationQueue = [[NSMutableArray alloc] init]; + + _serviceProvider = [serviceProvider copy]; + _userID = [userID copy]; + _userEmail = [userEmail copy]; + _userEmailIsVerified = [userEmailIsVerified copy]; + + // Decodes the ID Token locally to extract the email address. + NSString *idToken = _authState.lastTokenResponse.idToken + ? : _authState.lastAuthorizationResponse.idToken; + if (idToken) { + NSDictionary *claimsDictionary = [[OIDIDToken alloc] initWithIDTokenString:idToken].claims; + if (claimsDictionary) { + _userEmail = (NSString *)[claimsDictionary[@"email"] copy]; + _userEmailIsVerified = [(NSNumber *)claimsDictionary[@"email_verified"] stringValue]; + _userID = [claimsDictionary[@"sub"] copy]; + } + } + } + return self; +} + +# pragma mark - Convenience + +#if !GTM_APPAUTH_SKIP_GOOGLE_SUPPORT ++ (OIDServiceConfiguration *)configurationForGoogle { + NSURL *authorizationEndpoint = + [NSURL URLWithString:@"https://accounts.google.com/o/oauth2/v2/auth"]; + NSURL *tokenEndpoint = + [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"]; + + OIDServiceConfiguration *configuration = + [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpoint + tokenEndpoint:tokenEndpoint]; + return configuration; +} +#endif // !GTM_APPAUTH_SKIP_GOOGLE_SUPPORT + +#pragma mark - Authorizing Requests + +/*! @brief Internal routine common to delegate and block invocations to queue requests while + fresh tokens are obtained. + */ +- (void)authorizeRequestArgs:(GTMAppAuthFetcherAuthorizationArgs *)args { + // Adds requests to queue. + @synchronized(_authorizationQueue) { + [_authorizationQueue addObject:args]; + } + + NSDictionary *additionalRefreshParameters = _tokenRefreshDelegate ? + [_tokenRefreshDelegate additionalRefreshParameters:self] : nil; + + // Obtains fresh tokens from AppAuth. + [_authState performActionWithFreshTokens:^(NSString *_Nullable accessToken, + NSString *_Nullable idToken, + NSError *_Nullable error) { + // Processes queue. + @synchronized(self->_authorizationQueue) { + for (GTMAppAuthFetcherAuthorizationArgs *fetcherArgs in self->_authorizationQueue) { + [self authorizeRequestImmediateArgs:fetcherArgs accessToken:accessToken error:error]; + } + [self->_authorizationQueue removeAllObjects]; + } + } + additionalRefreshParameters:additionalRefreshParameters]; +} + +/*! @brief Adds authorization headers to the given request, using the supplied access token, or + handles the error. + @param args The request argument group to authorize. + @param accessToken A currently valid access token. + @param error If accessToken is nil, the error which caused the token to be unavailable. + @return YES if the request was authorized with a valid access token. + */ +- (BOOL)authorizeRequestImmediateArgs:(GTMAppAuthFetcherAuthorizationArgs *)args + accessToken:(NSString *)accessToken + error:(NSError *)error { + // This authorization entry point never attempts to refresh the access token, + // but does call the completion routine + + NSMutableURLRequest *request = args.request; + + NSURL *requestURL = [request URL]; + NSString *scheme = [requestURL scheme]; + BOOL isAuthorizableRequest = + !requestURL + || (scheme && [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame) + || [requestURL isFileURL] + || self.shouldAuthorizeAllRequests; + if (!isAuthorizableRequest) { + // Request is not https, a local file, or nil, so may be insecure + // + // The NSError will be created below +#if DEBUG + NSLog(@"Cannot authorize request with scheme %@ (%@)", scheme, request); +#endif + } + + // Get the access token. + if (isAuthorizableRequest && accessToken && accessToken.length > 0) { + if (request) { + // Adds the authorization header to the request. + NSString *value = [NSString stringWithFormat:@"%@ %@", @"Bearer", accessToken]; + [request setValue:value forHTTPHeaderField:@"Authorization"]; + } + + // We've authorized the request, even if the previous refresh + // failed with an error + args.error = nil; + } else { + NSMutableDictionary *userInfo = [error.userInfo mutableCopy]; + if (!userInfo) { + userInfo = [[NSMutableDictionary alloc] init]; + } + if (request) { + userInfo[GTMAppAuthFetcherAuthorizationErrorRequestKey] = request; + } + + if (!isAuthorizableRequest || !error) { + args.error = [NSError errorWithDomain:GTMAppAuthFetcherAuthorizationErrorDomain + code:GTMAppAuthFetcherAuthorizationErrorUnauthorizableRequest + userInfo:userInfo]; + } else { + // Passes through error domain & code from AppAuth, with additional userInfo args. + args.error = [NSError errorWithDomain:error.domain + code:error.code + userInfo:userInfo]; + } + } + + // Invoke any callbacks on the proper thread + if (args.delegate || args.completionHandler) { + // If the fetcher service provides a callback queue, we'll use that + // (or if it's nil, we'll use the main thread) for callbacks. + dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + dispatch_async(callbackQueue, ^{ + [self invokeCallbackArgs:args]; + }); + } + + BOOL didAuth = (args.error == nil); + return didAuth; +} + +/*! @brief Invokes the callback for the given authorization argument group. + @param args The request argument group to invoke following authorization or error. + */ +- (void)invokeCallbackArgs:(GTMAppAuthFetcherAuthorizationArgs *)args { + NSError *error = args.error; + id delegate = args.delegate; + SEL sel = args.selector; + + // If the selector callback method exists, invokes the selector. + if (delegate && sel) { + NSMutableURLRequest *request = args.request; + + NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate]; + GTMAppAuthFetcherAuthorization *authorization = self; + [invocation setArgument:&authorization atIndex:2]; + [invocation setArgument:&request atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + + // If a callback block exists, executes the block. + id handler = args.completionHandler; + if (handler) { + void (^authCompletionBlock)(NSError *) = handler; + authCompletionBlock(error); + } +} + +#pragma mark - GTMFetcherAuthorizationProtocol + +/*! @brief Authorizing with a callback selector. + @discussion Selector has the signature: + - (void)authentication:(GTMAppAuthFetcherAuthorization *)auth + request:(NSMutableURLRequest *)request + finishedWithError:(NSError *)error; + */ +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel { + GTMOAuth2AssertValidSelector(delegate, sel, + @encode(GTMAppAuthFetcherAuthorization *), + @encode(NSMutableURLRequest *), + @encode(NSError *), 0); + + GTMAppAuthFetcherAuthorizationArgs *args; + args = [GTMAppAuthFetcherAuthorizationArgs argsWithRequest:request + delegate:delegate + selector:sel + completionHandler:nil]; + [self authorizeRequestArgs:args]; +} + +/*! @brief Removes all pending requests from the authorization queue. + */ +- (void)stopAuthorization { + @synchronized(_authorizationQueue) { + [_authorizationQueue removeAllObjects]; + } +} + +/*! @brief Attempts to remove a specific pending requests from the authorization queue. + @discussion Has no effect if the authorization already occurred. + */ +- (void)stopAuthorizationForRequest:(NSURLRequest *)request { + @synchronized(_authorizationQueue) { + NSUInteger argIndex = 0; + BOOL found = NO; + for (GTMAppAuthFetcherAuthorizationArgs *args in _authorizationQueue) { + // Checks pointer equality with given request, don't want to match equivalent requests. + if ([args request] == request) { + found = YES; + break; + } + argIndex++; + } + + if (found) { + [_authorizationQueue removeObjectAtIndex:argIndex]; + + // If the queue is now empty, go ahead and stop the fetcher. + if (_authorizationQueue.count == 0) { + [self stopAuthorization]; + } + } + } +} + +/*! @brief Returns YES if the given requests is in the pending authorization queue. + */ +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request { + BOOL wasFound = NO; + @synchronized(_authorizationQueue) { + for (GTMAppAuthFetcherAuthorizationArgs *args in _authorizationQueue) { + // Checks pointer equality with given request, don't want to match equivalent requests. + if ([args request] == request) { + wasFound = YES; + break; + } + } + } + return wasFound; +} + +/*! @brief Returns YES if given request has an Authorization header. + */ +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request { + NSString *authStr = [request valueForHTTPHeaderField:@"Authorization"]; + return (authStr.length > 0); +} + +/*! @brief Returns YES if the authorization state is currently valid. + @discussion Note that the state can become invalid immediately due to an error on token refresh. + */ +- (BOOL)canAuthorize { + return [_authState isAuthorized]; +} + +/*! @brief Authorizing with a completion block. + */ +- (void)authorizeRequest:(NSMutableURLRequest *)request + completionHandler:(GTMAppAuthFetcherAuthorizationCompletion)handler { + GTMAppAuthFetcherAuthorizationArgs *args = + [GTMAppAuthFetcherAuthorizationArgs argsWithRequest:request + delegate:nil + selector:NULL + completionHandler:handler]; + [self authorizeRequestArgs:args]; +} + +/*! @brief Forces a token refresh the next time a request is queued for authorization. + */ +- (BOOL)primeForRefresh { + if (_authState.refreshToken == nil) { + // Cannot refresh without a refresh token + return NO; + } + [_authState setNeedsTokenRefresh]; + return YES; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDAuthState *authState = + [aDecoder decodeObjectOfClass:[OIDAuthState class] forKey:kAuthStateKey]; + NSString *serviceProvider = + [aDecoder decodeObjectOfClass:[NSString class] forKey:kServiceProviderKey]; + NSString *userID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserIDKey]; + NSString *userEmail = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserEmailKey]; + NSString *userEmailIsVerified = + [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserEmailIsVerifiedKey]; + + self = [self initWithAuthState:authState + serviceProvider:serviceProvider + userID:userID + userEmail:userEmail + userEmailIsVerified:userEmailIsVerified]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_authState forKey:kAuthStateKey]; + [aCoder encodeObject:_serviceProvider forKey:kServiceProviderKey]; + [aCoder encodeObject:_userID forKey:kUserIDKey]; + [aCoder encodeObject:_userEmail forKey:kUserEmailKey]; + [aCoder encodeObject:_userEmailIsVerified forKey:kUserEmailIsVerifiedKey]; +} + +@end diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMKeychain.h b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMKeychain.h new file mode 100644 index 00000000..b4d5d062 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMKeychain.h @@ -0,0 +1,62 @@ +/*! @file GTMKeychain.h + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Utility for saving and loading data to the keychain. + */ +@interface GTMKeychain : NSObject + +/*! @brief Saves the password string to the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @param password Password string to save. + @return YES when the password string was saved successfully. + */ ++ (BOOL)savePasswordToKeychainForName:(NSString *)keychainItemName password:(NSString *)password; + +/*! @brief Loads the password string from the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @return The password string at the given identifier, or nil. + */ ++ (nullable NSString *)passwordFromKeychainForName:(NSString *)keychainItemName; + +/*! @brief Saves the password data to the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @param passwordData Password data to save. + @return YES when the password data was saved successfully. + */ ++ (BOOL)savePasswordDataToKeychainForName:(NSString *)keychainItemName + passwordData:(NSData *)passwordData; + +/*! @brief Loads the password data from the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @return The password data at the given identifier, or nil. + */ ++ (nullable NSData *)passwordDataFromKeychainForName:(NSString *)keychainItemName; + +/*! @brief Removes stored password string, such as when the user signs out. + @param keychainItemName Keychain name of the item. + @return YES if the password string was removed successfully (or didn't exist). + */ ++ (BOOL)removePasswordFromKeychainForName:(NSString *)keychainItemName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.h b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.h new file mode 100644 index 00000000..9c0c5bf1 --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.h @@ -0,0 +1,131 @@ +/*! @file GTMOAuth2Compatibility.h + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMAppAuthFetcherAuthorization.h" + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Class to support serialization and deserialization of @c GTMAppAuthFetcherAuthorization + in the format used by GTMOAuth2. + @discussion The methods of this class are capable of serializing and deserializing auth + objects in a way compatible with the serialization in @c GTMOAuth2ViewControllerTouch and + @c GTMOAuth2WindowController in GTMOAuth2. + */ +@interface GTMOAuth2KeychainCompatibility : NSObject + +/*! @brief Encodes the given @c GTMAppAuthFetcherAuthorization in a GTMOAuth2 compatible persistence + string using URL param key/value encoding. + @param authorization The @c GTMAppAuthFetcherAuthorization to serialize in GTMOAuth2 format. + @return The GTMOAuth2 persistence representation of this object. + */ ++ (NSString *)persistenceResponseStringForAuthorization: + (GTMAppAuthFetcherAuthorization *)authorization; + +/*! @brief Attempts to create a @c GTMAppAuthFetcherAuthorization from data stored in the keychain + in GTMOAuth2 format, at the supplied keychain identifier. + @param keychainItemName The keychain name. + @param tokenURL The OAuth token endpoint URL. + @param redirectURI The OAuth redirect URI used when obtaining the original authorization. + @param clientID The OAuth client id. + @param clientSecret The OAuth client secret. + @return A @c GTMAppAuthFetcherAuthorization object, or nil. + */ ++ (nullable GTMAppAuthFetcherAuthorization *) + authorizeFromKeychainForName:(NSString *)keychainItemName + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURI + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret; + +/*! @brief Attempts to create a @c GTMAppAuthFetcherAuthorization from a @c NSString + representation of the GTMOAuth2 keychain data. + @param persistenceString String representation of the GTMOAuth2 keychain data. + @param tokenURL The OAuth token endpoint URL. + @param redirectURI The OAuth redirect URI used when obtaining the original authorization. + @param clientID The OAuth client id. + @param clientSecret The OAuth client secret. + @return A @c GTMAppAuthFetcherAuthorization object, or nil. + */ ++ (nullable GTMAppAuthFetcherAuthorization *) + authorizeFromPersistenceString:(NSString *)persistenceString + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURI + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret; + +/*! @brief Removes stored tokens, such as when the user signs out. + @param keychainItemName The keychain name. + @return YES the tokens were removed successfully (or didn't exist). + */ ++ (BOOL)removeAuthFromKeychainForName:(NSString *)keychainItemName; + +/*! @brief Saves the authorization state to the keychain, in a GTMOAuth2 compatible manner. + @param keychainItemName The keychain name. + @return YES when the state was saved successfully. + */ ++ (BOOL)saveAuthToKeychainForName:(NSString *)keychainItemName + authentication:(GTMAppAuthFetcherAuthorization *)auth + __attribute__((deprecated( + "Use GTMAppAuthFetcherAuthorization::saveAuthorization:toKeychainForName:"))); + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +/*! @brief Attempts to create a @c GTMAppAuthFetcherAuthorization from data stored in the keychain + in GTMOAuth2 format, at the supplied keychain identifier. Uses Google OAuth provider + information. + @param keychainItemName The keychain name. + @param clientID The OAuth client id. + @param clientSecret The OAuth client secret. + @return A @c GTMAppAuthFetcherAuthorization object, or nil. + */ ++ (nullable GTMAppAuthFetcherAuthorization *) + authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret; + +/*! @brief Returns Google's OAuth 2.0 authorization endpoint. + @return Returns Google's OAuth 2.0 authorization endpoint. + */ ++ (NSURL *)googleAuthorizationURL; + +/*! @brief Returns Google's OAuth 2.0 token endpoint. + @return Returns Google's OAuth 2.0 token endpoint. + */ ++ (NSURL *)googleTokenURL; + +/*! @brief Returns Google's OAuth 2.0 revocation endpoint. + @return Returns Google's OAuth 2.0 revocation endpoint. + */ ++ (NSURL *)googleRevocationURL; + +/*! @brief Returns Google's OAuth 2.0 userinfo endpoint. + @return Returns Google's OAuth 2.0 userinfo endpoint. + */ ++ (NSURL *)googleUserInfoURL; + +/*! @brief Returns Google's native OOB redirect URI. + @discussion This is a legacy redirect URI that was used with WebViews. + @return Returns Google's native OOB redirect URI. + */ ++ (NSString *)nativeClientRedirectURI; + +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.m b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.m new file mode 100644 index 00000000..5e56341b --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.m @@ -0,0 +1,325 @@ +/*! @file GTMOAuth2Compatibility.m + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMOAuth2KeychainCompatibility.h" + +#ifndef GTMAPPAUTH_USER_IMPORTS +#import +#else // GTMAPPAUTH_USER_IMPORTS +#import "AppAuthCore.h" +#endif // GTMAPPAUTH_USER_IMPORTS + +#import "GTMKeychain.h" + +// standard OAuth keys +static NSString *const kOAuth2AccessTokenKey = @"access_token"; +static NSString *const kOAuth2RefreshTokenKey = @"refresh_token"; +static NSString *const kOAuth2ScopeKey = @"scope"; +static NSString *const kOAuth2ErrorKey = @"error"; +static NSString *const kOAuth2TokenTypeKey = @"token_type"; +static NSString *const kOAuth2ExpiresInKey = @"expires_in"; +static NSString *const kOAuth2CodeKey = @"code"; +static NSString *const kOAuth2AssertionKey = @"assertion"; +static NSString *const kOAuth2RefreshScopeKey = @"refreshScope"; + +// additional persistent keys +static NSString *const kServiceProviderKey = @"serviceProvider"; +static NSString *const kUserIDKey = @"userID"; +static NSString *const kUserEmailKey = @"email"; +static NSString *const kUserEmailIsVerifiedKey = @"isVerified"; + +// URI indicating an installed app is signing in. This is described at +// +// https://developers.google.com/identity/protocols/OAuth2InstalledApp#formingtheurl +// +static NSString *const kOOBString = @"urn:ietf:wg:oauth:2.0:oob"; + +@implementation GTMOAuth2KeychainCompatibility + +// This returns a "response string" that can be passed later to +// setKeysForResponseString: to reuse an old access token in a new auth object ++ (NSString *)persistenceResponseStringForAuthorization: + (GTMAppAuthFetcherAuthorization *)authorization { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + + NSString *refreshToken = authorization.authState.refreshToken; + NSString *accessToken = authorization.authState.lastTokenResponse.accessToken; + + // Any nil values will not set a dictionary entry + [dict setValue:refreshToken forKey:kOAuth2RefreshTokenKey]; + [dict setValue:accessToken forKey:kOAuth2AccessTokenKey]; + [dict setValue:authorization.serviceProvider forKey:kServiceProviderKey]; + [dict setValue:authorization.userID forKey:kUserIDKey]; + [dict setValue:authorization.userEmail forKey:kUserEmailKey]; + [dict setValue:authorization.userEmailIsVerified forKey:kUserEmailIsVerifiedKey]; + [dict setValue:authorization.authState.scope forKey:kOAuth2ScopeKey]; + + NSString *result = [self encodedQueryParametersForDictionary:dict]; + return result; +} + ++ (GTMAppAuthFetcherAuthorization *)authorizeFromKeychainForName:(NSString *)keychainItemName + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURI + clientID:(NSString *)clientID + clientSecret:(nullable NSString *)clientSecret { + // Loads password string from keychain. + NSString *password = [GTMKeychain passwordFromKeychainForName:keychainItemName]; + + if (!password) { + return nil; + } + + GTMAppAuthFetcherAuthorization *authorization = + [self authorizeFromPersistenceString:password + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:clientSecret]; + return authorization; +} + ++ (GTMAppAuthFetcherAuthorization *)authorizeFromPersistenceString:(NSString *)persistenceString + tokenURL:(NSURL *)tokenURL + redirectURI:(NSString *)redirectURIString + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret { + // Parses persistence data into NSDictionary. + NSDictionary *dict = [self dictionaryWithResponseString:persistenceString]; + + NSURL *redirectURI = (NSURL *)[NSURL URLWithString:redirectURIString]; + + // OIDAuthState is based on the request/response history. + // Creates history based on the data from the keychain, and client details passed in. + OIDServiceConfiguration *authConfig = + [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:tokenURL tokenEndpoint:tokenURL]; + OIDAuthorizationRequest *authRequest = + [[OIDAuthorizationRequest alloc] initWithConfiguration:authConfig + clientId:clientID + clientSecret:clientSecret + scope:dict[kOAuth2ScopeKey] + redirectURL:redirectURI + responseType:OIDResponseTypeCode + state:nil + nonce:nil + codeVerifier:nil + codeChallenge:nil + codeChallengeMethod:nil + additionalParameters:nil]; + OIDAuthorizationResponse *authResponse = + [[OIDAuthorizationResponse alloc] initWithRequest:authRequest parameters:dict]; + // Exclude scope and refresh token parameters from additionalParameters. + NSMutableDictionary *additionalParameters = [dict mutableCopy]; + [additionalParameters removeObjectForKey:kOAuth2ScopeKey]; + [additionalParameters removeObjectForKey:kOAuth2RefreshTokenKey]; + OIDTokenRequest *tokenRequest = + [[OIDTokenRequest alloc] initWithConfiguration:authConfig + grantType:@"token" + authorizationCode:nil + redirectURL:redirectURI + clientID:clientID + clientSecret:clientSecret + scope:dict[kOAuth2ScopeKey] + refreshToken:dict[kOAuth2RefreshTokenKey] + codeVerifier:nil + additionalParameters:additionalParameters]; + OIDTokenResponse *tokenResponse = + [[OIDTokenResponse alloc] initWithRequest:tokenRequest parameters:dict]; + OIDAuthState *authState = [[OIDAuthState alloc] initWithAuthorizationResponse:authResponse + tokenResponse:tokenResponse]; + // We're not serializing the token expiry date, so the first refresh needs to be forced. + [authState setNeedsTokenRefresh]; + + GTMAppAuthFetcherAuthorization *authorizer = + [[GTMAppAuthFetcherAuthorization alloc] initWithAuthState:authState + serviceProvider:dict[kServiceProviderKey] + userID:dict[kUserIDKey] + userEmail:dict[kUserEmailKey] + userEmailIsVerified:dict[kUserEmailIsVerifiedKey]]; + return authorizer; +} + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + ++ (GTMAppAuthFetcherAuthorization *)authForGoogleFromKeychainForName:(NSString *)keychainItemName + clientID:(NSString *)clientID + clientSecret:(NSString *)clientSecret { + Class signInClass = self; + NSURL *tokenURL = [signInClass googleTokenURL]; + NSString *redirectURI = [signInClass nativeClientRedirectURI]; + + GTMAppAuthFetcherAuthorization *auth; + auth = [self authorizeFromKeychainForName:keychainItemName + tokenURL:tokenURL + redirectURI:redirectURI + clientID:clientID + clientSecret:clientSecret]; + return auth; +} + +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +/*! @brief Removes stored tokens, such as when the user signs out. + @return YES the tokens were removed successfully (or didn't exist). + */ ++ (BOOL)removeAuthFromKeychainForName:(NSString *)keychainItemName { + return [GTMKeychain removePasswordFromKeychainForName:keychainItemName]; +} + +/*! @brief Saves the authorization state to the keychain, in a GTMOAuth2 compatible manner. + @return YES when the state was saved successfully. + */ ++ (BOOL)saveAuthToKeychainForName:(NSString *)keychainItemName + authentication:(GTMAppAuthFetcherAuthorization *)auth { + [self removeAuthFromKeychainForName:keychainItemName]; + NSString *password = [self persistenceResponseStringForAuthorization:auth]; + + return [GTMKeychain savePasswordToKeychainForName:keychainItemName password:password]; +} + +#pragma mark Utility Routines + ++ (NSString *)encodedQueryParametersForDictionary:(NSDictionary *)dict { + // Make a string like "cat=fluffy&dog=spot" + NSMutableString *result = [NSMutableString string]; + NSArray *sortedKeys = + [[dict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSString *joiner = @""; + for (NSString *key in sortedKeys) { + NSString *value = [dict objectForKey:key]; + NSString *encodedValue = [self encodedOAuthValueForString:value]; + NSString *encodedKey = [self encodedOAuthValueForString:key]; + [result appendFormat:@"%@%@=%@", joiner, encodedKey, encodedValue]; + joiner = @"&"; + } + return result; +} + ++ (NSString *)encodedOAuthValueForString:(NSString *)originalString { + // For parameters, we'll explicitly leave spaces unescaped now, and replace + // them with +'s + NSString *const kForceEscape = @"!*'();:@&=+$,/?%#[]"; + +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_7_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0) + // Builds targeting iOS 7/OS X 10.9 and higher only. + NSMutableCharacterSet *cs = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + [cs removeCharactersInString:kForceEscape]; + + return [originalString stringByAddingPercentEncodingWithAllowedCharacters:cs]; +#else + // Builds targeting iOS 6/OS X 10.8. + CFStringRef escapedStr = NULL; + if (originalString) { + escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, + (CFStringRef)originalString, + NULL, + (CFStringRef)kForceEscape, + kCFStringEncodingUTF8); + } + + return (__bridge NSString *)escapedStr; +#endif +} + ++ (NSDictionary *)dictionaryWithResponseString:(NSString *)responseStr { + // Build a dictionary from a response string of the form + // "cat=fluffy&dog=spot". Missing or empty values are considered + // empty strings; keys and values are percent-decoded. + if (responseStr == nil) return nil; + + NSArray *items = [responseStr componentsSeparatedByString:@"&"]; + + NSMutableDictionary *responseDict = [NSMutableDictionary dictionaryWithCapacity:items.count]; + + for (NSString *item in items) { + NSString *key; + NSString *value = @""; + + NSRange equalsRange = [item rangeOfString:@"="]; + if (equalsRange.location != NSNotFound) { + // The parameter has at least one '=' + key = [item substringToIndex:equalsRange.location]; + + // There are characters after the '=' + if (equalsRange.location + 1 < item.length) { + value = [item substringFromIndex:(equalsRange.location + 1)]; + } + } else { + // The parameter has no '=' + key = item; + } + + NSString *plainKey = [self unencodedOAuthParameterForString:key]; + NSString *plainValue = [self unencodedOAuthParameterForString:value]; + + [responseDict setObject:plainValue forKey:plainKey]; + } + + return responseDict; +} + ++ (NSString *)unencodedOAuthParameterForString:(NSString *)str { +#if (!TARGET_OS_IPHONE \ + && defined(MAC_OS_X_VERSION_10_9) \ + && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9) \ + || (TARGET_OS_IPHONE \ + && defined(__IPHONE_7_0) \ + && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0) + // On iOS 7, -stringByRemovingPercentEncoding incorrectly returns nil for an empty string. + if (str != nil && [str length] == 0) return @""; + + NSString *plainStr = [str stringByRemovingPercentEncoding]; + return plainStr; +#else + NSString *plainStr = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return plainStr; +#endif +} + +#if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +// Endpoint URLs are available at https://accounts.google.com/.well-known/openid-configuration + ++ (NSURL *)googleAuthorizationURL { + NSString *str = @"https://accounts.google.com/o/oauth2/v2/auth"; + return (NSURL *)[NSURL URLWithString:str]; +} + ++ (NSURL *)googleTokenURL { + NSString *str = @"https://www.googleapis.com/oauth2/v4/token"; + return (NSURL *)[NSURL URLWithString:str]; +} + ++ (NSURL *)googleRevocationURL { + NSString *urlStr = @"https://accounts.google.com/o/oauth2/revoke"; + return (NSURL *)[NSURL URLWithString:urlStr]; +} + ++ (NSURL *)googleUserInfoURL { + NSString *urlStr = @"https://www.googleapis.com/oauth2/v3/userinfo"; + return (NSURL *)[NSURL URLWithString:urlStr]; +} + ++ (NSString *)nativeClientRedirectURI { + return kOOBString; +} + +#endif // !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT + +@end diff --git a/MyExperiences copy/Pods/GTMAppAuth/Source/iOS/GTMKeychain_iOS.m b/MyExperiences copy/Pods/GTMAppAuth/Source/iOS/GTMKeychain_iOS.m new file mode 100644 index 00000000..ab64882e --- /dev/null +++ b/MyExperiences copy/Pods/GTMAppAuth/Source/iOS/GTMKeychain_iOS.m @@ -0,0 +1,287 @@ +/*! @file GTMKeychain_iOS.m + @brief GTMAppAuth SDK + @copyright + Copyright 2016 Google Inc. + @copydetails + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "GTMKeychain.h" + +#import + +typedef NS_ENUM(NSInteger, GTMAppAuthFetcherAuthorizationGTMAppAuthGTMOAuth2KeychainError) { + GTMAppAuthGTMOAuth2KeychainErrorBadArguments = -1301, + GTMAppAuthGTMOAuth2KeychainErrorNoPassword = -1302 +}; + +/*! @brief Keychain helper class. + */ +@interface GTMAppAuthGTMOAuth2Keychain : NSObject + ++ (GTMAppAuthGTMOAuth2Keychain *)defaultKeychain; + +// OK to pass nil for the error parameter. +- (NSString *)passwordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error; + +- (NSData *)passwordDataForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error; + +// OK to pass nil for the error parameter. +- (BOOL)removePasswordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error; + +// OK to pass nil for the error parameter. +// +// accessibility should be one of the constants for kSecAttrAccessible +// such as kSecAttrAccessibleWhenUnlocked +- (BOOL)setPassword:(NSString *)password + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error; + +- (BOOL)setPasswordData:(NSData *)passwordData + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error; + +// For unit tests: allow setting a mock object ++ (void)setDefaultKeychain:(GTMAppAuthGTMOAuth2Keychain *)keychain; + +@end + +NSString *const kGTMAppAuthFetcherAuthorizationGTMOAuth2ErrorDomain = @"com.google.GTMOAuth2"; +NSString *const kGTMAppAuthFetcherAuthorizationGTMOAuth2KeychainErrorDomain = + @"com.google.GTMOAuthKeychain"; +static NSString *const kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName = @"OAuth"; +static GTMAppAuthGTMOAuth2Keychain* gGTMAppAuthFetcherAuthorizationGTMOAuth2DefaultKeychain = nil; + +@implementation GTMKeychain + ++ (BOOL)removePasswordFromKeychainForName:(NSString *)keychainItemName { + GTMAppAuthGTMOAuth2Keychain *keychain = [GTMAppAuthGTMOAuth2Keychain defaultKeychain]; + return [keychain removePasswordForService:keychainItemName + account:kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName + error:nil]; +} + ++ (NSString *)passwordFromKeychainForName:(NSString *)keychainItemName { + GTMAppAuthGTMOAuth2Keychain *keychain = [GTMAppAuthGTMOAuth2Keychain defaultKeychain]; + NSError *error; + NSString *password = + [keychain passwordForService:keychainItemName + account:kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName + error:&error]; + return password; +} + ++ (BOOL)savePasswordToKeychainForName:(NSString *)keychainItemName password:(NSString *)password { + return [self savePasswordToKeychainForName:keychainItemName + password:password + accessibility:NULL + error:NULL]; +} + ++ (BOOL)savePasswordToKeychainForName:(NSString *)keychainItemName password:(NSString *)password + accessibility:(CFTypeRef)accessibility + error:(NSError **)error { + if (accessibility == NULL) { + accessibility = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + } + // make a response string containing the values we want to save + GTMAppAuthGTMOAuth2Keychain *keychain = [GTMAppAuthGTMOAuth2Keychain defaultKeychain]; + return [keychain setPassword:password + forService:keychainItemName + accessibility:accessibility + account:kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName + error:error]; +} + +/*! @brief Saves the password string to the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @param password Password string to save. + @return YES when the password string was saved successfully. + */ ++ (BOOL)savePasswordDataToKeychainForName:(NSString *)keychainItemName + passwordData:(NSData *)password { + CFTypeRef accessibility = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + // make a response string containing the values we want to save + GTMAppAuthGTMOAuth2Keychain *keychain = [GTMAppAuthGTMOAuth2Keychain defaultKeychain]; + return [keychain setPasswordData:password + forService:keychainItemName + accessibility:accessibility + account:kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName + error:NULL]; +} + +/*! @brief Loads the password string from the keychain with the given identifier. + @param keychainItemName Keychain name of the item. + @return The password string at the given identifier, or nil. + */ ++ (NSData *)passwordDataFromKeychainForName:(NSString *)keychainItemName { + GTMAppAuthGTMOAuth2Keychain *keychain = [GTMAppAuthGTMOAuth2Keychain defaultKeychain]; + NSError *error; + NSData *password = + [keychain passwordDataForService:keychainItemName + account:kGTMAppAuthFetcherAuthorizationGTMOAuth2AccountName + error:&error]; + return password; +} + +@end + +#pragma mark GTMAppAuthGTMOAuth2Keychain + +@implementation GTMAppAuthGTMOAuth2Keychain + ++ (GTMAppAuthGTMOAuth2Keychain *)defaultKeychain { + static dispatch_once_t onceToken; + dispatch_once (&onceToken, ^{ + gGTMAppAuthFetcherAuthorizationGTMOAuth2DefaultKeychain = [[self alloc] init]; + }); + return gGTMAppAuthFetcherAuthorizationGTMOAuth2DefaultKeychain; +} + + +// For unit tests: allow setting a mock object ++ (void)setDefaultKeychain:(GTMAppAuthGTMOAuth2Keychain *)keychain { + if (gGTMAppAuthFetcherAuthorizationGTMOAuth2DefaultKeychain != keychain) { + gGTMAppAuthFetcherAuthorizationGTMOAuth2DefaultKeychain = keychain; + } +} + +- (NSString *)keyForService:(NSString *)service account:(NSString *)account { + return [NSString stringWithFormat:@"com.google.GTMOAuth.%@%@", service, account]; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + NSMutableDictionary *query = + [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword, (id)kSecClass, + @"OAuth", (id)kSecAttrGeneric, + account, (id)kSecAttrAccount, + service, (id)kSecAttrService, + nil]; + return query; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account]; +} + +// iPhone +- (NSString *)passwordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error { + NSData *passwordData = [self passwordDataForService:service account:account error:error]; + if (!passwordData) { + return nil; + } + NSString *result = [[NSString alloc] initWithData:passwordData + encoding:NSUTF8StringEncoding]; + return result; +} + +// iPhone +- (NSData *)passwordDataForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error { + OSStatus status = GTMAppAuthGTMOAuth2KeychainErrorBadArguments; + NSData *result = nil; + if (service.length > 0 && account.length > 0) { + CFDataRef passwordData = NULL; + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; + [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; + + status = SecItemCopyMatching((CFDictionaryRef)keychainQuery, + (CFTypeRef *)&passwordData); + if (status == noErr && 0 < [(__bridge NSData *)passwordData length]) { + result = [(__bridge NSData *)passwordData copy]; + } + if (passwordData != NULL) { + CFRelease(passwordData); + } + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMAppAuthFetcherAuthorizationGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return result; +} + +// iPhone +- (BOOL)removePasswordForService:(NSString *)service + account:(NSString *)account + error:(NSError **)error { + OSStatus status = GTMAppAuthGTMOAuth2KeychainErrorBadArguments; + if (0 < [service length] && 0 < [account length]) { + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + status = SecItemDelete((CFDictionaryRef)keychainQuery); + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMAppAuthFetcherAuthorizationGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return status == noErr; +} + +// iPhone +- (BOOL)setPassword:(NSString *)password + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error { + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + return [self setPasswordData:passwordData + forService:service + accessibility:accessibility + account:account + error:error]; +} + +- (BOOL)setPasswordData:(NSData *)passwordData + forService:(NSString *)service + accessibility:(CFTypeRef)accessibility + account:(NSString *)account + error:(NSError **)error { + OSStatus status = GTMAppAuthGTMOAuth2KeychainErrorBadArguments; + if (0 < [service length] && 0 < [account length]) { + [self removePasswordForService:service account:account error:nil]; + if (0 < [passwordData length]) { + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [keychainQuery setObject:passwordData forKey:(id)kSecValueData]; + + if (accessibility != NULL) { + [keychainQuery setObject:(__bridge id)accessibility + forKey:(id)kSecAttrAccessible]; + } + status = SecItemAdd((CFDictionaryRef)keychainQuery, NULL); + } + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kGTMAppAuthFetcherAuthorizationGTMOAuth2KeychainErrorDomain + code:status + userInfo:nil]; + } + return status == noErr; +} + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/LICENSE b/MyExperiences copy/Pods/GTMSessionFetcher/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/README.md b/MyExperiences copy/Pods/GTMSessionFetcher/README.md new file mode 100644 index 00000000..478efde9 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/README.md @@ -0,0 +1,23 @@ +# Google Toolbox for Mac - Session Fetcher # + +**Project site**
+**Discussion group** + +[![Build Status](https://travis-ci.org/google/gtm-session-fetcher.svg?branch=master)](https://travis-ci.org/google/gtm-session-fetcher) + +`GTMSessionFetcher` makes it easy for Cocoa applications to perform http +operations. The fetcher is implemented as a wrapper on `NSURLSession`, so its +behavior is asynchronous and uses operating-system settings on iOS and Mac OS X. + +Features include: +- Simple to build; only one source/header file pair is required +- Simple to use: takes just two lines of code to fetch a request +- Supports upload and download sessions +- Flexible cookie storage +- Automatic retry on errors, with exponential backoff +- Support for generating multipart MIME upload streams +- Easy, convenient logging of http requests and responses +- Supports plug-in authentication such as with GTMAppAuth +- Easily testable; self-mocking +- Automatic rate limiting when created by the `GTMSessionFetcherService` factory class +- Fully independent of other projects diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.h new file mode 100644 index 00000000..ec3c0125 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.h @@ -0,0 +1,52 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// The GTMGatherInput stream is an input stream implementation that is to be +// instantiated with an NSArray of NSData objects. It works in the traditional +// scatter/gather vector I/O model. Rather than allocating a big NSData object +// to hold all of the data and performing a copy into that object, the +// GTMGatherInputStream will maintain a reference to the NSArray and read from +// each NSData in turn as the read method is called. You should not alter the +// underlying set of NSData objects until all read operations on this input +// stream have completed. + +#import + +#ifndef GTM_NONNULL + #if defined(__has_attribute) + #if __has_attribute(nonnull) + #define GTM_NONNULL(x) __attribute__((nonnull x)) + #else + #define GTM_NONNULL(x) + #endif + #else + #define GTM_NONNULL(x) + #endif +#endif + +// Avoid multiple declaration of this class. +// +// Note: This should match the declaration of GTMGatherInputStream in GTMMIMEDocument.m + +#ifndef GTM_GATHERINPUTSTREAM_DECLARED +#define GTM_GATHERINPUTSTREAM_DECLARED + +@interface GTMGatherInputStream : NSInputStream + ++ (NSInputStream *)streamWithArray:(NSArray *)dataArray GTM_NONNULL((1)); + +@end + +#endif // GTM_GATHERINPUTSTREAM_DECLARED diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.m new file mode 100644 index 00000000..0f65310f --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMGatherInputStream.m @@ -0,0 +1,185 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMGatherInputStream.h" + +@implementation GTMGatherInputStream { + NSArray *_dataArray; // NSDatas that should be "gathered" and streamed. + NSUInteger _arrayIndex; // Index in the array of the current NSData. + long long _dataOffset; // Offset in the current NSData we are processing. + NSStreamStatus _streamStatus; + id __weak _delegate; // Stream delegate, defaults to self. +} + ++ (NSInputStream *)streamWithArray:(NSArray *)dataArray { + return [(GTMGatherInputStream *)[self alloc] initWithArray:dataArray]; +} + +- (instancetype)initWithArray:(NSArray *)dataArray { + self = [super init]; + if (self) { + _dataArray = dataArray; + _delegate = self; // An NSStream's default delegate should be self. + } + return self; +} + +#pragma mark - NSStream + +- (void)open { + _arrayIndex = 0; + _dataOffset = 0; + _streamStatus = NSStreamStatusOpen; +} + +- (void)close { + _streamStatus = NSStreamStatusClosed; +} + +- (id)delegate { + return _delegate; +} + +- (void)setDelegate:(id)delegate { + if (delegate == nil) { + _delegate = self; + } else { + _delegate = delegate; + } +} + +- (id)propertyForKey:(NSString *)key { + if ([key isEqual:NSStreamFileCurrentOffsetKey]) { + return @([self absoluteOffset]); + } + return nil; +} + +- (BOOL)setProperty:(id)property forKey:(NSString *)key { + if ([key isEqual:NSStreamFileCurrentOffsetKey]) { + NSNumber *absoluteOffsetNumber = property; + [self setAbsoluteOffset:absoluteOffsetNumber.longLongValue]; + return YES; + } + return NO; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { +} + +- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { +} + +- (NSStreamStatus)streamStatus { + return _streamStatus; +} + +- (NSError *)streamError { + return nil; +} + +#pragma mark - NSInputStream + +- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len { + NSInteger bytesRead = 0; + NSUInteger bytesRemaining = len; + + // Read bytes from the currently-indexed array. + while ((bytesRemaining > 0) && (_arrayIndex < _dataArray.count)) { + NSData *data = [_dataArray objectAtIndex:_arrayIndex]; + + NSUInteger dataLen = data.length; + NSUInteger dataBytesLeft = dataLen - (NSUInteger)_dataOffset; + + NSUInteger bytesToCopy = MIN(bytesRemaining, dataBytesLeft); + NSRange range = NSMakeRange((NSUInteger) _dataOffset, bytesToCopy); + + [data getBytes:(buffer + bytesRead) range:range]; + + bytesRead += bytesToCopy; + _dataOffset += bytesToCopy; + bytesRemaining -= bytesToCopy; + + if (_dataOffset == (long long)dataLen) { + _dataOffset = 0; + _arrayIndex++; + } + } + if (_arrayIndex >= _dataArray.count) { + _streamStatus = NSStreamStatusAtEnd; + } + return bytesRead; +} + +- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len { + return NO; // We don't support this style of reading. +} + +- (BOOL)hasBytesAvailable { + // If we return no, the read never finishes, even if we've already delivered all the bytes. + return YES; +} + +#pragma mark - NSStreamDelegate + +- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { + id delegate = _delegate; + if (delegate != self) { + [delegate stream:self handleEvent:streamEvent]; + } +} + +#pragma mark - Private + +- (long long)absoluteOffset { + long long absoluteOffset = 0; + NSUInteger index = 0; + for (NSData *data in _dataArray) { + if (index >= _arrayIndex) { + break; + } + absoluteOffset += data.length; + ++index; + } + absoluteOffset += _dataOffset; + return absoluteOffset; +} + +- (void)setAbsoluteOffset:(long long)absoluteOffset { + if (absoluteOffset < 0) { + absoluteOffset = 0; + } + _arrayIndex = 0; + _dataOffset = absoluteOffset; + for (NSData *data in _dataArray) { + long long dataLen = (long long) data.length; + if (dataLen > _dataOffset) { + break; + } + _arrayIndex++; + _dataOffset -= dataLen; + } + if (_arrayIndex == _dataArray.count) { + if (_dataOffset > 0) { + _dataOffset = 0; + } + } +} + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.h new file mode 100644 index 00000000..451e1323 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.h @@ -0,0 +1,148 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is a simple class to create or parse a MIME document. + +// To create a MIME document, allocate a new GTMMIMEDocument and start adding parts. +// When you are done adding parts, call generateInputStream or generateDispatchData. +// +// A good reference for MIME is http://en.wikipedia.org/wiki/MIME + +#import + +#ifndef GTM_NONNULL + #if defined(__has_attribute) + #if __has_attribute(nonnull) + #define GTM_NONNULL(x) __attribute__((nonnull x)) + #else + #define GTM_NONNULL(x) + #endif + #else + #define GTM_NONNULL(x) + #endif +#endif + +#ifndef GTM_DECLARE_GENERICS + #if __has_feature(objc_generics) + #define GTM_DECLARE_GENERICS 1 + #else + #define GTM_DECLARE_GENERICS 0 + #endif +#endif + +#ifndef GTM_NSArrayOf + #if GTM_DECLARE_GENERICS + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #else + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #endif // GTM_DECLARE_GENERICS +#endif // GTM_NSArrayOf + + +// GTMMIMEDocumentPart represents a part of a MIME document. +// +// +[GTMMIMEDocument MIMEPartsWithBoundary:data:] returns an array of these. +@interface GTMMIMEDocumentPart : NSObject + +@property(nonatomic, readonly) GTM_NSDictionaryOf(NSString *, NSString *) *headers; +@property(nonatomic, readonly) NSData *headerData; +@property(nonatomic, readonly) NSData *body; +@property(nonatomic, readonly) NSUInteger length; + ++ (instancetype)partWithHeaders:(NSDictionary *)headers body:(NSData *)body; + +@end + +@interface GTMMIMEDocument : NSObject + +// Get or set the unique boundary for the parts that have been added. +// +// When creating a MIME document from parts, this is typically calculated +// automatically after all parts have been added. +@property(nonatomic, copy) NSString *boundary; + +#pragma mark - Methods for Creating a MIME Document + ++ (instancetype)MIMEDocument; + +// Adds a new part to this mime document with the given headers and body. +// The headers keys and values should be NSStrings. +// Adding a part may cause the boundary string to change. +- (void)addPartWithHeaders:(GTM_NSDictionaryOf(NSString *, NSString *) *)headers + body:(NSData *)body GTM_NONNULL((1,2)); + +// An inputstream that can be used to efficiently read the contents of the MIME document. +// +// Any parameter may be null if the result is not wanted. +- (void)generateInputStream:(NSInputStream **)outStream + length:(unsigned long long *)outLength + boundary:(NSString **)outBoundary; + +// A dispatch_data_t with the contents of the MIME document. +// +// Note: dispatch_data_t is one-way toll-free bridged so the result +// may be cast directly to NSData *. +// +// Any parameter may be null if the result is not wanted. +- (void)generateDispatchData:(dispatch_data_t *)outDispatchData + length:(unsigned long long *)outLength + boundary:(NSString **)outBoundary; + +// Utility method for making a header section, including trailing newlines. ++ (NSData *)dataWithHeaders:(GTM_NSDictionaryOf(NSString *, NSString *) *)headers; + +#pragma mark - Methods for Parsing a MIME Document + +// Method for parsing out an array of MIME parts from a MIME document. +// +// Returns an array of GTMMIMEDocumentParts. Returns nil if no part can +// be found. ++ (GTM_NSArrayOf(GTMMIMEDocumentPart *) *)MIMEPartsWithBoundary:(NSString *)boundary + data:(NSData *)fullDocumentData; + +// Utility method for efficiently searching possibly discontiguous NSData +// for occurrences of target byte. This method does not "flatten" an NSData +// that is composed of discontiguous blocks. +// +// The byte offsets of non-overlapping occurrences of the target are returned as +// NSNumbers in the array. ++ (void)searchData:(NSData *)data + targetBytes:(const void *)targetBytes + targetLength:(NSUInteger)targetLength + foundOffsets:(GTM_NSArrayOf(NSNumber *) **)outFoundOffsets; + +// Utility method to parse header bytes into an NSDictionary. ++ (GTM_NSDictionaryOf(NSString *, NSString *) *)headersWithData:(NSData *)data; + +// ------ UNIT TESTING ONLY BELOW ------ + +// Internal methods, exposed for unit testing only. +- (void)seedRandomWith:(u_int32_t)seed; + ++ (NSUInteger)findBytesWithNeedle:(const unsigned char *)needle + needleLength:(NSUInteger)needleLength + haystack:(const unsigned char *)haystack + haystackLength:(NSUInteger)haystackLength + foundOffset:(NSUInteger *)foundOffset; + ++ (void)searchData:(NSData *)data + targetBytes:(const void *)targetBytes + targetLength:(NSUInteger)targetLength + foundOffsets:(GTM_NSArrayOf(NSNumber *) **)outFoundOffsets + foundBlockNumbers:(GTM_NSArrayOf(NSNumber *) **)outFoundBlockNumbers; + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.m new file mode 100644 index 00000000..f4460c5d --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMMIMEDocument.m @@ -0,0 +1,631 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMMIMEDocument.h" + +// Avoid a hard dependency on GTMGatherInputStream. +#ifndef GTM_GATHERINPUTSTREAM_DECLARED +#define GTM_GATHERINPUTSTREAM_DECLARED + +@interface GTMGatherInputStream : NSInputStream + ++ (NSInputStream *)streamWithArray:(NSArray *)dataArray GTM_NONNULL((1)); + +@end +#endif // GTM_GATHERINPUTSTREAM_DECLARED + +// FindBytes +// +// Helper routine to search for the existence of a set of bytes (needle) within +// a presumed larger set of bytes (haystack). Can find the first part of the +// needle at the very end of the haystack. +// +// Returns the needle length on complete success, the number of bytes matched +// if a partial needle was found at the end of the haystack, and 0 on failure. +static NSUInteger FindBytes(const unsigned char *needle, NSUInteger needleLen, + const unsigned char *haystack, NSUInteger haystackLen, + NSUInteger *foundOffset); + +// SearchDataForBytes +// +// This implements the functionality of the +searchData: methods below. See the documentation +// for those methods. +static void SearchDataForBytes(NSData *data, const void *targetBytes, NSUInteger targetLength, + NSMutableArray *foundOffsets, NSMutableArray *foundBlockNumbers); + +@implementation GTMMIMEDocumentPart { + NSDictionary *_headers; + NSData *_headerData; // Header content including the ending "\r\n". + NSData *_bodyData; +} + +@synthesize headers = _headers, + headerData = _headerData, + body = _bodyData; + +@dynamic length; + ++ (instancetype)partWithHeaders:(NSDictionary *)headers body:(NSData *)body { + return [[self alloc] initWithHeaders:headers body:body]; +} + +- (instancetype)initWithHeaders:(NSDictionary *)headers body:(NSData *)body { + self = [super init]; + if (self) { + _bodyData = body; + _headers = headers; + } + return self; +} + +// Returns true if the part's header or data contain the given set of bytes. +// +// NOTE: We assume that the 'bytes' we are checking for do not contain "\r\n", +// so we don't need to check the concatenation of the header and body bytes. +- (BOOL)containsBytes:(const unsigned char *)bytes length:(NSUInteger)length { + // This uses custom search code rather than strcpy because the encoded data may contain + // null values. + NSData *headerData = self.headerData; + return (FindBytes(bytes, length, headerData.bytes, headerData.length, NULL) == length || + FindBytes(bytes, length, _bodyData.bytes, _bodyData.length, NULL) == length); +} + +- (NSData *)headerData { + if (!_headerData) { + _headerData = [GTMMIMEDocument dataWithHeaders:_headers]; + } + return _headerData; +} + +- (NSData *)body { + return _bodyData; +} + +- (NSUInteger)length { + return _headerData.length + _bodyData.length; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p (headers %lu keys, body %lu bytes)", + [self class], self, (unsigned long)_headers.count, + (unsigned long)_bodyData.length]; +} + +- (BOOL)isEqual:(GTMMIMEDocumentPart *)other { + if (self == other) return YES; + if (![other isKindOfClass:[GTMMIMEDocumentPart class]]) return NO; + return ((_bodyData == other->_bodyData || [_bodyData isEqual:other->_bodyData]) + && (_headers == other->_headers || [_headers isEqual:other->_headers])); +} + +- (NSUInteger)hash { + return _bodyData.hash | _headers.hash; +} + +@end + +@implementation GTMMIMEDocument { + NSMutableArray *_parts; // Ordered array of GTMMIMEDocumentParts. + unsigned long long _length; // Length in bytes of the document. + NSString *_boundary; + u_int32_t _randomSeed; // For testing. +} + ++ (instancetype)MIMEDocument { + return [[self alloc] init]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _parts = [[NSMutableArray alloc] init]; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p (%lu parts)", + [self class], self, (unsigned long)_parts.count]; +} + +#pragma mark - Joining Parts + +// Adds a new part to this mime document with the given headers and body. +- (void)addPartWithHeaders:(NSDictionary *)headers body:(NSData *)body { + GTMMIMEDocumentPart *part = [GTMMIMEDocumentPart partWithHeaders:headers body:body]; + [_parts addObject:part]; + _boundary = nil; +} + +// For unit testing only, seeds the random number generator so that we will +// have reproducible boundary strings. +- (void)seedRandomWith:(u_int32_t)seed { + _randomSeed = seed; + _boundary = nil; +} + +- (u_int32_t)random { + if (_randomSeed) { + // For testing only. + return _randomSeed++; + } else { + return arc4random(); + } +} + +// Computes the mime boundary to use. This should only be called +// after all the desired document parts have been added since it must compute +// a boundary that does not exist in the document data. +- (NSString *)boundary { + if (_boundary) { + return _boundary; + } + + // Use an easily-readable boundary string. + NSString *const kBaseBoundary = @"END_OF_PART"; + + _boundary = kBaseBoundary; + + // If the boundary isn't unique, append random numbers, up to 10 attempts; + // if that's still not unique, use a random number sequence instead, and call it good. + BOOL didCollide = NO; + + const int maxTries = 10; // Arbitrarily chosen maximum attempts. + for (int tries = 0; tries < maxTries; ++tries) { + + NSData *data = [_boundary dataUsingEncoding:NSUTF8StringEncoding]; + const void *dataBytes = data.bytes; + NSUInteger dataLen = data.length; + + for (GTMMIMEDocumentPart *part in _parts) { + didCollide = [part containsBytes:dataBytes length:dataLen]; + if (didCollide) break; + } + + if (!didCollide) break; // We're fine, no more attempts needed. + + // Try again with a random number appended. + _boundary = [NSString stringWithFormat:@"%@_%08x", kBaseBoundary, [self random]]; + } + + if (didCollide) { + // Fallback... two random numbers. + _boundary = [NSString stringWithFormat:@"%08x_tedborg_%08x", [self random], [self random]]; + } + return _boundary; +} + +- (void)setBoundary:(NSString *)str { + _boundary = [str copy]; +} + +// Internal method. +- (void)generateDataArray:(NSMutableArray *)dataArray + length:(unsigned long long *)outLength + boundary:(NSString **)outBoundary { + + // The input stream is of the form: + // --boundary + // [part_1_headers] + // [part_1_data] + // --boundary + // [part_2_headers] + // [part_2_data] + // --boundary-- + + // First we set up our boundary NSData objects. + NSString *boundary = self.boundary; + + NSString *mainBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n", boundary]; + NSString *endBoundary = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary]; + + NSData *mainBoundaryData = [mainBoundary dataUsingEncoding:NSUTF8StringEncoding]; + NSData *endBoundaryData = [endBoundary dataUsingEncoding:NSUTF8StringEncoding]; + + // Now we add them all in proper order to our dataArray. + unsigned long long length = 0; + + for (GTMMIMEDocumentPart *part in _parts) { + [dataArray addObject:mainBoundaryData]; + [dataArray addObject:part.headerData]; + [dataArray addObject:part.body]; + + length += part.length + mainBoundaryData.length; + } + + [dataArray addObject:endBoundaryData]; + length += endBoundaryData.length; + + if (outLength) *outLength = length; + if (outBoundary) *outBoundary = boundary; +} + +- (void)generateInputStream:(NSInputStream **)outStream + length:(unsigned long long *)outLength + boundary:(NSString **)outBoundary { + NSMutableArray *dataArray = outStream ? [NSMutableArray array] : nil; + [self generateDataArray:dataArray + length:outLength + boundary:outBoundary]; + + if (outStream) { + Class streamClass = NSClassFromString(@"GTMGatherInputStream"); + NSAssert(streamClass != nil, @"GTMGatherInputStream not available."); + + *outStream = [streamClass streamWithArray:dataArray]; + } +} + +- (void)generateDispatchData:(dispatch_data_t *)outDispatchData + length:(unsigned long long *)outLength + boundary:(NSString **)outBoundary { + NSMutableArray *dataArray = outDispatchData ? [NSMutableArray array] : nil; + [self generateDataArray:dataArray + length:outLength + boundary:outBoundary]; + + if (outDispatchData) { + // Create an empty data accumulator. + dispatch_data_t dataAccumulator; + + dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + for (NSData *partData in dataArray) { + __block NSData *immutablePartData = [partData copy]; + dispatch_data_t newDataPart = + dispatch_data_create(immutablePartData.bytes, immutablePartData.length, bgQueue, ^{ + // We want the data retained until this block executes. + immutablePartData = nil; + }); + + if (dataAccumulator == nil) { + // First part. + dataAccumulator = newDataPart; + } else { + // Append the additional part. + dataAccumulator = dispatch_data_create_concat(dataAccumulator, newDataPart); + } + } + *outDispatchData = dataAccumulator; + } +} + ++ (NSData *)dataWithHeaders:(NSDictionary *)headers { + // Generate the header data by coalescing the dictionary as lines of "key: value\r\n". + NSMutableString* headerString = [NSMutableString string]; + + // Sort the header keys so we have a deterministic order for unit testing. + SEL sortSel = @selector(caseInsensitiveCompare:); + NSArray *sortedKeys = [headers.allKeys sortedArrayUsingSelector:sortSel]; + + for (NSString *key in sortedKeys) { + NSString *value = [headers objectForKey:key]; + +#if DEBUG + // Look for troublesome characters in the header keys & values. + NSCharacterSet *badKeyChars = [NSCharacterSet characterSetWithCharactersInString:@":\r\n"]; + NSCharacterSet *badValueChars = [NSCharacterSet characterSetWithCharactersInString:@"\r\n"]; + + NSRange badRange = [key rangeOfCharacterFromSet:badKeyChars]; + NSAssert(badRange.location == NSNotFound, @"invalid key: %@", key); + + badRange = [value rangeOfCharacterFromSet:badValueChars]; + NSAssert(badRange.location == NSNotFound, @"invalid value: %@", value); +#endif + + [headerString appendFormat:@"%@: %@\r\n", key, value]; + } + // Headers end with an extra blank line. + [headerString appendString:@"\r\n"]; + + NSData *result = [headerString dataUsingEncoding:NSUTF8StringEncoding]; + return result; +} + +#pragma mark - Separating Parts + ++ (NSArray *)MIMEPartsWithBoundary:(NSString *)boundary + data:(NSData *)fullDocumentData { + // In MIME documents, the boundary is preceded by CRLF and two dashes, and followed + // at the end by two dashes. + NSData *boundaryData = [boundary dataUsingEncoding:NSUTF8StringEncoding]; + NSUInteger boundaryLength = boundaryData.length; + + NSMutableArray *foundBoundaryOffsets; + [self searchData:fullDocumentData + targetBytes:boundaryData.bytes + targetLength:boundaryLength + foundOffsets:&foundBoundaryOffsets]; + + // According to rfc1341, ignore anything before the first boundary, or after the last, though two + // dashes are expected to follow the last boundary. + if (foundBoundaryOffsets.count < 2) { + return nil; + } + + // Wrap the full document data with a dispatch_data_t for more efficient slicing + // and dicing. + dispatch_data_t dataWrapper; + if ([fullDocumentData conformsToProtocol:@protocol(OS_dispatch_data)]) { + dataWrapper = (dispatch_data_t)fullDocumentData; + } else { + // A no-op self invocation on fullDocumentData will keep it retained until the block is invoked. + dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dataWrapper = dispatch_data_create(fullDocumentData.bytes, + fullDocumentData.length, + bgQueue, ^{ [fullDocumentData self]; }); + } + NSMutableArray *parts; + NSInteger previousBoundaryOffset = -1; + NSInteger partCounter = -1; + NSInteger numberOfPartsWithHeaders = 0; + for (NSNumber *currentBoundaryOffset in foundBoundaryOffsets) { + ++partCounter; + if (previousBoundaryOffset == -1) { + // This is the first boundary. + previousBoundaryOffset = currentBoundaryOffset.integerValue; + continue; + } else { + // Create a part data subrange between the previous boundary and this one. + // + // The last four bytes before a boundary are CRLF--. + // The first two bytes following a boundary are either CRLF or, for the last boundary, --. + NSInteger previousPartDataStartOffset = + previousBoundaryOffset + (NSInteger)boundaryLength + 2; + NSInteger previousPartDataEndOffset = currentBoundaryOffset.integerValue - 4; + NSInteger previousPartDataLength = previousPartDataEndOffset - previousPartDataStartOffset; + + if (previousPartDataLength < 2) { + // The preceding part was too short to be useful. +#if DEBUG + NSLog(@"MIME part %ld has %ld bytes", (long)partCounter - 1, + (long)previousPartDataLength); +#endif + } else { + if (!parts) parts = [NSMutableArray array]; + + dispatch_data_t partData = + dispatch_data_create_subrange(dataWrapper, + (size_t)previousPartDataStartOffset, (size_t)previousPartDataLength); + // Scan the part data for the separator between headers and body. After the CRLF, + // either the headers start immediately, or there's another CRLF and there are no headers. + // + // We need to map the part data to get the first two bytes. (Or we could cast it to + // NSData and get the bytes pointer of that.) If we're concerned that a single part + // data may be expensive to map, we could make a subrange here for just the first two bytes, + // and map that two-byte subrange. + const void *partDataBuffer; + size_t partDataBufferSize; + dispatch_data_t mappedPartData NS_VALID_UNTIL_END_OF_SCOPE = + dispatch_data_create_map(partData, &partDataBuffer, &partDataBufferSize); + dispatch_data_t bodyData; + NSDictionary *headers; + BOOL hasAnotherCRLF = (((char *)partDataBuffer)[0] == '\r' + && ((char *)partDataBuffer)[1] == '\n'); + mappedPartData = nil; + + if (hasAnotherCRLF) { + // There are no headers; skip the CRLF to get to the body, and leave headers nil. + bodyData = dispatch_data_create_subrange(partData, 2, (size_t)previousPartDataLength - 2); + } else { + // There are part headers. They are separated from body data by CRLFCRLF. + NSArray *crlfOffsets; + [self searchData:(NSData *)partData + targetBytes:"\r\n\r\n" + targetLength:4 + foundOffsets:&crlfOffsets]; + if (crlfOffsets.count == 0) { +#if DEBUG + // We could not distinguish body and headers. + NSLog(@"MIME part %ld lacks a header separator: %@", (long)partCounter - 1, + [[NSString alloc] initWithData:(NSData *)partData encoding:NSUTF8StringEncoding]); +#endif + } else { + NSInteger headerSeparatorOffset = ((NSNumber *)crlfOffsets.firstObject).integerValue; + dispatch_data_t headerData = + dispatch_data_create_subrange(partData, 0, (size_t)headerSeparatorOffset); + headers = [self headersWithData:(NSData *)headerData]; + + bodyData = dispatch_data_create_subrange(partData, (size_t)headerSeparatorOffset + 4, + (size_t)(previousPartDataLength - (headerSeparatorOffset + 4))); + + numberOfPartsWithHeaders++; + } // crlfOffsets.count == 0 + } // hasAnotherCRLF + GTMMIMEDocumentPart *part = [GTMMIMEDocumentPart partWithHeaders:headers + body:(NSData *)bodyData]; + [parts addObject:part]; + } // previousPartDataLength < 2 + previousBoundaryOffset = currentBoundaryOffset.integerValue; + } + } +#if DEBUG + // In debug builds, warn if a reasonably long document lacks any CRLF characters. + if (numberOfPartsWithHeaders == 0) { + NSUInteger length = fullDocumentData.length; + if (length > 20) { // Reasonably long. + NSMutableArray *foundCRLFs; + [self searchData:fullDocumentData + targetBytes:"\r\n" + targetLength:2 + foundOffsets:&foundCRLFs]; + if (foundCRLFs.count == 0) { + // Parts were logged above (due to lacking header separators.) + NSLog(@"Warning: MIME document lacks any headers (may have wrong line endings)"); + } + } + } +#endif // DEBUG + return parts; +} + +// Efficiently search the supplied data for the target bytes. +// +// This uses enumerateByteRangesUsingBlock: to scan for bytes. It can find +// the target even if it spans multiple separate byte ranges. +// +// Returns an array of found byte offset values, as NSNumbers. ++ (void)searchData:(NSData *)data + targetBytes:(const void *)targetBytes + targetLength:(NSUInteger)targetLength + foundOffsets:(GTM_NSArrayOf(NSNumber *) **)outFoundOffsets { + NSMutableArray *foundOffsets = [NSMutableArray array]; + SearchDataForBytes(data, targetBytes, targetLength, foundOffsets, NULL); + *outFoundOffsets = foundOffsets; +} + + +// This version of searchData: also returns the block numbers (0-based) where the +// target was found, used for testing that the supplied dispatch_data buffer +// has not been flattened. ++ (void)searchData:(NSData *)data + targetBytes:(const void *)targetBytes + targetLength:(NSUInteger)targetLength + foundOffsets:(GTM_NSArrayOf(NSNumber *) **)outFoundOffsets + foundBlockNumbers:(GTM_NSArrayOf(NSNumber *) **)outFoundBlockNumbers { + NSMutableArray *foundOffsets = [NSMutableArray array]; + NSMutableArray *foundBlockNumbers = [NSMutableArray array]; + + SearchDataForBytes(data, targetBytes, targetLength, foundOffsets, foundBlockNumbers); + *outFoundOffsets = foundOffsets; + *outFoundBlockNumbers = foundBlockNumbers; +} + +static void SearchDataForBytes(NSData *data, const void *targetBytes, NSUInteger targetLength, + NSMutableArray *foundOffsets, NSMutableArray *foundBlockNumbers) { + __block NSUInteger priorPartialMatchAmount = 0; + __block NSInteger priorPartialMatchStartingBlockNumber = -1; + __block NSInteger blockNumber = -1; + + [data enumerateByteRangesUsingBlock:^(const void *bytes, + NSRange byteRange, + BOOL *stop) { + // Search for the first character in the current range. + const void *ptr = bytes; + NSInteger remainingInCurrentRange = (NSInteger)byteRange.length; + ++blockNumber; + + if (priorPartialMatchAmount > 0) { + NSUInteger amountRemainingToBeMatched = targetLength - priorPartialMatchAmount; + NSUInteger remainingFoundOffset; + NSUInteger amountMatched = FindBytes(targetBytes + priorPartialMatchAmount, + amountRemainingToBeMatched, + ptr, (NSUInteger)remainingInCurrentRange, &remainingFoundOffset); + if (amountMatched == 0 || remainingFoundOffset > 0) { + // No match of the rest of the prior partial match in this range. + } else if (amountMatched < amountRemainingToBeMatched) { + // Another partial match; we're done with this range. + priorPartialMatchAmount = priorPartialMatchAmount + amountMatched; + return; + } else { + // The offset is in an earlier range. + NSUInteger offset = byteRange.location - priorPartialMatchAmount; + [foundOffsets addObject:@(offset)]; + [foundBlockNumbers addObject:@(priorPartialMatchStartingBlockNumber)]; + priorPartialMatchStartingBlockNumber = -1; + } + priorPartialMatchAmount = 0; + } + + while (remainingInCurrentRange > 0) { + NSUInteger offsetFromPtr; + NSUInteger amountMatched = FindBytes(targetBytes, targetLength, ptr, + (NSUInteger)remainingInCurrentRange, &offsetFromPtr); + if (amountMatched == 0) { + // No match in this range. + return; + } + if (amountMatched < targetLength) { + // Found a partial target. If there's another range, we'll check for the rest. + priorPartialMatchAmount = amountMatched; + priorPartialMatchStartingBlockNumber = blockNumber; + return; + } + // Found the full target. + NSUInteger globalOffset = byteRange.location + (NSUInteger)(ptr - bytes) + offsetFromPtr; + + [foundOffsets addObject:@(globalOffset)]; + [foundBlockNumbers addObject:@(blockNumber)]; + + ptr += targetLength + offsetFromPtr; + remainingInCurrentRange -= (targetLength + offsetFromPtr); + } + }]; +} + +// Internal method only for testing; this calls through the static method. ++ (NSUInteger)findBytesWithNeedle:(const unsigned char *)needle + needleLength:(NSUInteger)needleLength + haystack:(const unsigned char *)haystack + haystackLength:(NSUInteger)haystackLength + foundOffset:(NSUInteger *)foundOffset { + return FindBytes(needle, needleLength, haystack, haystackLength, foundOffset); +} + +// Utility method to parse header bytes into an NSDictionary. ++ (NSDictionary *)headersWithData:(NSData *)data { + NSString *headersString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (!headersString) return nil; + + NSMutableDictionary *headers = [NSMutableDictionary dictionary]; + NSScanner *scanner = [NSScanner scannerWithString:headersString]; + // The scanner is skipping leading whitespace and newline characters by default. + NSCharacterSet *newlineCharacters = [NSCharacterSet newlineCharacterSet]; + NSString *key; + NSString *value; + while ([scanner scanUpToString:@":" intoString:&key] + && [scanner scanString:@":" intoString:NULL] + && [scanner scanUpToCharactersFromSet:newlineCharacters intoString:&value]) { + [headers setObject:value forKey:key]; + // Discard the trailing newline. + [scanner scanCharactersFromSet:newlineCharacters intoString:NULL]; + } + return headers; +} + +@end + +// Return how much of the needle was found in the haystack. +// +// If the result is less than needleLen, then the beginning of the needle +// was found at the end of the haystack. +static NSUInteger FindBytes(const unsigned char* needle, NSUInteger needleLen, + const unsigned char* haystack, NSUInteger haystackLen, + NSUInteger *foundOffset) { + const unsigned char *ptr = haystack; + NSInteger remain = (NSInteger)haystackLen; + // Assume memchr is an efficient way to find a match for the first + // byte of the needle, and memcmp is an efficient way to compare a + // range of bytes. + while (remain > 0 && (ptr = memchr(ptr, needle[0], (size_t)remain)) != 0) { + // The first character is present. + NSUInteger offset = (NSUInteger)(ptr - haystack); + remain = (NSInteger)(haystackLen - offset); + + NSUInteger amountToCompare = MIN((NSUInteger)remain, needleLen); + if (memcmp(ptr, needle, amountToCompare) == 0) { + if (foundOffset) *foundOffset = offset; + return amountToCompare; + } + ptr++; + remain--; + } + if (foundOffset) *foundOffset = 0; + return 0; +} diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.h new file mode 100644 index 00000000..4e306428 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.h @@ -0,0 +1,49 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef GTM_NONNULL + #if defined(__has_attribute) + #if __has_attribute(nonnull) + #define GTM_NONNULL(x) __attribute__((nonnull x)) + #else + #define GTM_NONNULL(x) + #endif + #else + #define GTM_NONNULL(x) + #endif +#endif + + +@interface GTMReadMonitorInputStream : NSInputStream + ++ (instancetype)inputStreamWithStream:(NSInputStream *)input GTM_NONNULL((1)); + +- (instancetype)initWithStream:(NSInputStream *)input GTM_NONNULL((1)); + +// The read monitor selector is called when bytes have been read. It should have this signature: +// +// - (void)inputStream:(GTMReadMonitorInputStream *)stream +// readIntoBuffer:(uint8_t *)buffer +// length:(int64_t)length; + +@property(atomic, weak) id readDelegate; +@property(atomic, assign) SEL readSelector; + +// Modes for invoking callbacks, when necessary. +@property(atomic, strong) NSArray *runLoopModes; + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.m new file mode 100644 index 00000000..6f95dd54 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMReadMonitorInputStream.m @@ -0,0 +1,190 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMReadMonitorInputStream.h" + +@implementation GTMReadMonitorInputStream { + NSInputStream *_inputStream; // Encapsulated stream that does the work. + + NSThread *_thread; // Thread in which this object was created. + NSArray *_runLoopModes; // Modes for calling callbacks, when necessary. +} + + +@synthesize readDelegate = _readDelegate; +@synthesize readSelector = _readSelector; +@synthesize runLoopModes = _runLoopModes; + +// We'll forward all unhandled messages to the NSInputStream class or to the encapsulated input +// stream. This is needed for all messages sent to NSInputStream which aren't handled by our +// superclass; that includes various private run loop calls. ++ (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSInputStream methodSignatureForSelector:selector]; +} + ++ (void)forwardInvocation:(NSInvocation*)invocation { + [invocation invokeWithTarget:[NSInputStream class]]; +} + +- (BOOL)respondsToSelector:(SEL)selector { + return [_inputStream respondsToSelector:selector]; +} + +- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { + return [_inputStream methodSignatureForSelector:selector]; +} + +- (void)forwardInvocation:(NSInvocation*)invocation { + [invocation invokeWithTarget:_inputStream]; +} + +#pragma mark - + ++ (instancetype)inputStreamWithStream:(NSInputStream *)input { + return [[self alloc] initWithStream:input]; +} + +- (instancetype)initWithStream:(NSInputStream *)input { + self = [super init]; + if (self) { + _inputStream = input; + _thread = [NSThread currentThread]; + } + return self; +} + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +#pragma mark - + +- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len { + // Read from the encapsulated stream. + NSInteger numRead = [_inputStream read:buffer maxLength:len]; + if (numRead > 0) { + if (_readDelegate && _readSelector) { + // Call the read selector with the buffer and number of bytes actually read into it. + BOOL isOnOriginalThread = [_thread isEqual:[NSThread currentThread]]; + if (isOnOriginalThread) { + // Invoke immediately. + NSData *data = [NSData dataWithBytesNoCopy:buffer + length:(NSUInteger)numRead + freeWhenDone:NO]; + [self invokeReadSelectorWithBuffer:data]; + } else { + // Copy the buffer into an NSData to be retained by the performSelector, + // and invoke on the proper thread. + SEL sel = @selector(invokeReadSelectorWithBuffer:); + NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numRead]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if (_runLoopModes) { + [self performSelector:sel + onThread:_thread + withObject:data + waitUntilDone:NO + modes:_runLoopModes]; + } else { + [self performSelector:sel + onThread:_thread + withObject:data + waitUntilDone:NO]; + } +#pragma clang diagnostic pop + } + } + } + return numRead; +} + +- (void)invokeReadSelectorWithBuffer:(NSData *)data { + const void *buffer = data.bytes; + int64_t length = (int64_t)data.length; + + id argSelf = self; + id readDelegate = _readDelegate; + if (readDelegate) { + NSMethodSignature *signature = [readDelegate methodSignatureForSelector:_readSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:_readSelector]; + [invocation setTarget:readDelegate]; + [invocation setArgument:&argSelf atIndex:2]; + [invocation setArgument:&buffer atIndex:3]; + [invocation setArgument:&length atIndex:4]; + [invocation invoke]; + } +} + +- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len { + return [_inputStream getBuffer:buffer length:len]; +} + +- (BOOL)hasBytesAvailable { + return [_inputStream hasBytesAvailable]; +} + +#pragma mark Standard messages + +// Pass expected messages to our encapsulated stream. +// +// We want our encapsulated NSInputStream to handle the standard messages; +// we don't want the superclass to handle them. +- (void)open { + [_inputStream open]; +} + +- (void)close { + [_inputStream close]; +} + +- (id)delegate { + return [_inputStream delegate]; +} + +- (void)setDelegate:(id)delegate { + [_inputStream setDelegate:delegate]; +} + +- (id)propertyForKey:(NSString *)key { + return [_inputStream propertyForKey:key]; +} + +- (BOOL)setProperty:(id)property forKey:(NSString *)key { + return [_inputStream setProperty:property forKey:key]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [_inputStream scheduleInRunLoop:aRunLoop forMode:mode]; +} + +- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode { + [_inputStream removeFromRunLoop:aRunLoop forMode:mode]; +} + +- (NSStreamStatus)streamStatus { + return [_inputStream streamStatus]; +} + +- (NSError *)streamError { + return [_inputStream streamError]; +} + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h new file mode 100644 index 00000000..0504aa75 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h @@ -0,0 +1,1332 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// GTMSessionFetcher is a wrapper around NSURLSession for http operations. +// +// What does this offer on top of of NSURLSession? +// +// - Block-style callbacks for useful functionality like progress rather +// than delegate methods. +// - Out-of-process uploads and downloads using NSURLSession, including +// management of fetches after relaunch. +// - Integration with GTMAppAuth for invisible management and refresh of +// authorization tokens. +// - Pretty-printed http logging. +// - Cookies handling that does not interfere with or get interfered with +// by WebKit cookies or on Mac by Safari and other apps. +// - Credentials handling for the http operation. +// - Rate-limiting and cookie grouping when fetchers are created with +// GTMSessionFetcherService. +// +// If the bodyData or bodyFileURL property is set, then a POST request is assumed. +// +// Each fetcher is assumed to be for a one-shot fetch request; don't reuse the object +// for a second fetch. +// +// The fetcher will be self-retained as long as a connection is pending. +// +// To keep user activity private, URLs must have an https scheme (unless the property +// allowedInsecureSchemes is set to permit the scheme.) +// +// Callbacks will be released when the fetch completes or is stopped, so there is no need +// to use weak self references in the callback blocks. +// +// Sample usage: +// +// _fetcherService = [[GTMSessionFetcherService alloc] init]; +// +// GTMSessionFetcher *myFetcher = [_fetcherService fetcherWithURLString:myURLString]; +// myFetcher.retryEnabled = YES; +// myFetcher.comment = @"First profile image"; +// +// // Optionally specify a file URL or NSData for the request body to upload. +// myFetcher.bodyData = [postString dataUsingEncoding:NSUTF8StringEncoding]; +// +// [myFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { +// if (error != nil) { +// // Server status code or network error. +// // +// // If the domain is kGTMSessionFetcherStatusDomain then the error code +// // is a failure status from the server. +// } else { +// // Fetch succeeded. +// } +// }]; +// +// There is also a beginFetch call that takes a pointer and selector for the completion handler; +// a pointer and selector is a better style when the callback is a substantial, separate method. +// +// NOTE: Fetches may retrieve data from the server even though the server +// returned an error, so the criteria for success is a non-nil error. +// The completion handler is called when the server status is >= 300 with an NSError +// having domain kGTMSessionFetcherStatusDomain and code set to the server status. +// +// Status codes are at +// +// +// Background session support: +// +// Out-of-process uploads and downloads may be created by setting the fetcher's +// useBackgroundSession property. Data to be uploaded should be provided via +// the uploadFileURL property; the download destination should be specified with +// the destinationFileURL. NOTE: Background upload files should be in a location +// that will be valid even after the device is restarted, so the file should not +// be uploaded from a system temporary or cache directory. +// +// Background session transfers are slower, and should typically be used only +// for very large downloads or uploads (hundreds of megabytes). +// +// When background sessions are used in iOS apps, the application delegate must +// pass through the parameters from UIApplicationDelegate's +// application:handleEventsForBackgroundURLSession:completionHandler: to the +// fetcher class. +// +// When the application has been relaunched, it may also create a new fetcher +// instance to handle completion of the transfers. +// +// - (void)application:(UIApplication *)application +// handleEventsForBackgroundURLSession:(NSString *)identifier +// completionHandler:(void (^)())completionHandler { +// // Application was re-launched on completing an out-of-process download. +// +// // Pass the URLSession info related to this re-launch to the fetcher class. +// [GTMSessionFetcher application:application +// handleEventsForBackgroundURLSession:identifier +// completionHandler:completionHandler]; +// +// // Get a fetcher related to this re-launch and re-hook up a completionHandler to it. +// GTMSessionFetcher *fetcher = [GTMSessionFetcher fetcherWithSessionIdentifier:identifier]; +// NSURL *destinationFileURL = fetcher.destinationFileURL; +// fetcher.completionHandler = ^(NSData *data, NSError *error) { +// [self downloadCompletedToFile:destinationFileURL error:error]; +// }; +// } +// +// +// Threading and queue support: +// +// Networking always happens on a background thread; there is no advantage to +// changing thread or queue to create or start a fetcher. +// +// Callbacks are run on the main thread; alternatively, the app may set the +// fetcher's callbackQueue to a dispatch queue. +// +// Once the fetcher's beginFetch method has been called, the fetcher's methods and +// properties may be accessed from any thread. +// +// Downloading to disk: +// +// To have downloaded data saved directly to disk, specify a file URL for the +// destinationFileURL property. +// +// HTTP methods and headers: +// +// Alternative HTTP methods, like PUT, and custom headers can be specified by +// creating the fetcher with an appropriate NSMutableURLRequest. +// +// +// Caching: +// +// The fetcher avoids caching. That is best for API requests, but may hurt +// repeat fetches of static data. Apps may enable a persistent disk cache by +// customizing the config: +// +// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher, +// NSURLSessionConfiguration *config) { +// config.URLCache = [NSURLCache sharedURLCache]; +// }; +// +// Or use the standard system config to share cookie storage with web views +// and to enable disk caching: +// +// fetcher.configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; +// +// +// Cookies: +// +// There are three supported mechanisms for remembering cookies between fetches. +// +// By default, a standalone GTMSessionFetcher uses a mutable array held +// statically to track cookies for all instantiated fetchers. This avoids +// cookies being set by servers for the application from interfering with +// Safari and WebKit cookie settings, and vice versa. +// The fetcher cookies are lost when the application quits. +// +// To rely instead on WebKit's global NSHTTPCookieStorage, set the fetcher's +// cookieStorage property: +// myFetcher.cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; +// +// To share cookies with other apps, use the method introduced in iOS 9/OS X 10.11: +// myFetcher.cookieStorage = +// [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:kMyCompanyContainedID]; +// +// To ignore existing cookies and only have cookies related to the single fetch +// be applied, make a temporary cookie storage object: +// myFetcher.cookieStorage = [[GTMSessionCookieStorage alloc] init]; +// +// Note: cookies set while following redirects will be sent to the server, as +// the redirects are followed by the fetcher. +// +// To completely disable cookies, similar to setting cookieStorageMethod to +// kGTMHTTPFetcherCookieStorageMethodNone, adjust the session configuration +// appropriately in the fetcher or fetcher service: +// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher, +// NSURLSessionConfiguration *config) { +// config.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever; +// config.HTTPShouldSetCookies = NO; +// }; +// +// If the fetcher is created from a GTMSessionFetcherService object +// then the cookie storage mechanism is set to use the cookie storage in the +// service object rather than the static storage. Disabling cookies in the +// session configuration set on a service object will disable cookies for all +// fetchers created from that GTMSessionFetcherService object, since the session +// configuration is propagated to the fetcher. +// +// +// Monitoring data transfers. +// +// The fetcher supports a variety of properties for progress monitoring +// progress with callback blocks. +// GTMSessionFetcherSendProgressBlock sendProgressBlock +// GTMSessionFetcherReceivedProgressBlock receivedProgressBlock +// GTMSessionFetcherDownloadProgressBlock downloadProgressBlock +// +// If supplied by the server, the anticipated total download size is available +// as [[myFetcher response] expectedContentLength] (and may be -1 for unknown +// download sizes.) +// +// +// Automatic retrying of fetches +// +// The fetcher can optionally create a timer and reattempt certain kinds of +// fetch failures (status codes 408, request timeout; 502, gateway failure; +// 503, service unavailable; 504, gateway timeout; networking errors +// NSURLErrorTimedOut and NSURLErrorNetworkConnectionLost.) The user may +// set a retry selector to customize the type of errors which will be retried. +// +// Retries are done in an exponential-backoff fashion (that is, after 1 second, +// 2, 4, 8, and so on.) +// +// Enabling automatic retries looks like this: +// myFetcher.retryEnabled = YES; +// +// With retries enabled, the completion callbacks are called only +// when no more retries will be attempted. Calling the fetcher's stopFetching +// method will terminate the retry timer, without the finished or failure +// selectors being invoked. +// +// Optionally, the client may set the maximum retry interval: +// myFetcher.maxRetryInterval = 60.0; // in seconds; default is 60 seconds +// // for downloads, 600 for uploads +// +// Servers should never send a 400 or 500 status for errors that are retryable +// by clients, as those values indicate permanent failures. In nearly all +// cases, the default standard retry behavior is correct for clients, and no +// custom client retry behavior is needed or appropriate. Servers that send +// non-retryable status codes and expect the client to retry the request are +// faulty. +// +// Still, the client may provide a block to determine if a status code or other +// error should be retried. The block returns YES to set the retry timer or NO +// to fail without additional fetch attempts. +// +// The retry method may return the |suggestedWillRetry| argument to get the +// default retry behavior. Server status codes are present in the +// error argument, and have the domain kGTMSessionFetcherStatusDomain. The +// user's method may look something like this: +// +// myFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *error, +// GTMSessionFetcherRetryResponse response) { +// // Perhaps examine error.domain and error.code, or fetcher.retryCount +// // +// // Respond with YES to start the retry timer, NO to proceed to the failure +// // callback, or suggestedWillRetry to get default behavior for the +// // current error domain and code values. +// response(suggestedWillRetry); +// }; + + +#import + +#if TARGET_OS_IPHONE +#import +#endif +#if TARGET_OS_WATCH +#import +#endif + +// By default it is stripped from non DEBUG builds. Developers can override +// this in their project settings. +#ifndef STRIP_GTM_FETCH_LOGGING + #if !DEBUG + #define STRIP_GTM_FETCH_LOGGING 1 + #else + #define STRIP_GTM_FETCH_LOGGING 0 + #endif +#endif + +// Logs in debug builds. +#ifndef GTMSESSION_LOG_DEBUG + #if DEBUG + #define GTMSESSION_LOG_DEBUG(...) NSLog(__VA_ARGS__) + #else + #define GTMSESSION_LOG_DEBUG(...) do { } while (0) + #endif +#endif + +// Asserts in debug builds (or logs in debug builds if GTMSESSION_ASSERT_AS_LOG +// or NS_BLOCK_ASSERTIONS are defined.) +#ifndef GTMSESSION_ASSERT_DEBUG + #if DEBUG && !defined(NS_BLOCK_ASSERTIONS) && !GTMSESSION_ASSERT_AS_LOG + #undef GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_AS_LOG 1 + #endif + + #if DEBUG && !GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_DEBUG(...) NSAssert(__VA_ARGS__) + #elif DEBUG + #define GTMSESSION_ASSERT_DEBUG(pred, ...) if (!(pred)) { NSLog(__VA_ARGS__); } + #else + #define GTMSESSION_ASSERT_DEBUG(pred, ...) do { } while (0) + #endif +#endif + +// Asserts in debug builds, logs in release builds (or logs in debug builds if +// GTMSESSION_ASSERT_AS_LOG is defined.) +#ifndef GTMSESSION_ASSERT_DEBUG_OR_LOG + #if DEBUG && !GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_DEBUG_OR_LOG(...) NSAssert(__VA_ARGS__) + #else + #define GTMSESSION_ASSERT_DEBUG_OR_LOG(pred, ...) if (!(pred)) { NSLog(__VA_ARGS__); } + #endif +#endif + +// Macro useful for examining messages from NSURLSession during debugging. +#if 0 +#define GTM_LOG_SESSION_DELEGATE(...) GTMSESSION_LOG_DEBUG(__VA_ARGS__) +#else +#define GTM_LOG_SESSION_DELEGATE(...) +#endif + +#ifndef GTM_NULLABLE + #if __has_feature(nullability) // Available starting in Xcode 6.3 + #define GTM_NULLABLE_TYPE __nullable + #define GTM_NONNULL_TYPE __nonnull + #define GTM_NULLABLE nullable + #define GTM_NONNULL_DECL nonnull // GTM_NONNULL is used by GTMDefines.h + #define GTM_NULL_RESETTABLE null_resettable + + #define GTM_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN + #define GTM_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END + #else + #define GTM_NULLABLE_TYPE + #define GTM_NONNULL_TYPE + #define GTM_NULLABLE + #define GTM_NONNULL_DECL + #define GTM_NULL_RESETTABLE + #define GTM_ASSUME_NONNULL_BEGIN + #define GTM_ASSUME_NONNULL_END + #endif // __has_feature(nullability) +#endif // GTM_NULLABLE + +#ifndef GTM_DECLARE_GENERICS + #if __has_feature(objc_generics) + #define GTM_DECLARE_GENERICS 1 + #else + #define GTM_DECLARE_GENERICS 0 + #endif +#endif + +#ifndef GTM_NSArrayOf + #if GTM_DECLARE_GENERICS + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #else + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #endif // __has_feature(objc_generics) +#endif // GTM_NSArrayOf + +// For iOS, the fetcher can declare itself a background task to allow fetches +// to finish when the app leaves the foreground. +// +// (This is unrelated to providing a background configuration, which allows +// out-of-process uploads and downloads.) +// +// To disallow use of background tasks during fetches, the target should define +// GTM_BACKGROUND_TASK_FETCHING to 0, or alternatively may set the +// skipBackgroundTask property to YES. +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !defined(GTM_BACKGROUND_TASK_FETCHING) + #define GTM_BACKGROUND_TASK_FETCHING 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if (TARGET_OS_TV \ + || TARGET_OS_WATCH \ + || (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0)) + #ifndef GTM_USE_SESSION_FETCHER + #define GTM_USE_SESSION_FETCHER 1 + #endif +#endif + +#if !defined(GTMBridgeFetcher) + // These bridge macros should be identical in GTMHTTPFetcher.h and GTMSessionFetcher.h + #if GTM_USE_SESSION_FETCHER + // Macros to new fetcher class. + #define GTMBridgeFetcher GTMSessionFetcher + #define GTMBridgeFetcherService GTMSessionFetcherService + #define GTMBridgeFetcherServiceProtocol GTMSessionFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMSessionFetcherAssertValidSelector + #define GTMBridgeCookieStorage GTMSessionCookieStorage + #define GTMBridgeCleanedUserAgentString GTMFetcherCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMFetcherSystemVersionString + #define GTMBridgeApplicationIdentifier GTMFetcherApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMSessionFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest GTMSessionFetcherStatusBadRequest + #else + // Macros to old fetcher class. + #define GTMBridgeFetcher GTMHTTPFetcher + #define GTMBridgeFetcherService GTMHTTPFetcherService + #define GTMBridgeFetcherServiceProtocol GTMHTTPFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMAssertSelectorNilOrImplementedWithArgs + #define GTMBridgeCookieStorage GTMCookieStorage + #define GTMBridgeCleanedUserAgentString GTMCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMSystemVersionString + #define GTMBridgeApplicationIdentifier GTMApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMHTTPFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest kGTMHTTPFetcherStatusBadRequest + #endif // GTM_USE_SESSION_FETCHER +#endif + +// When creating background sessions to perform out-of-process uploads and +// downloads, on app launch any background sessions must be reconnected in +// order to receive events that occurred while the app was not running. +// +// The fetcher will automatically attempt to recreate the sessions on app +// start, but doing so reads from NSUserDefaults. This may have launch-time +// performance impacts. +// +// To avoid launch performance impacts, on iPhone/iPad with iOS 13+ the +// GTMSessionFetcher class will register for the app launch notification and +// perform the reconnect then. +// +// Apps targeting Mac or older iOS SDKs can opt into the new behavior by defining +// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH=1. +// +// Apps targeting new SDKs can force the old behavior by defining +// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH = 0. +#ifndef GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH + // Default to the on-launch behavior for iOS 13+. + #if TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 + #define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 1 + #else + #define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 0 + #endif +#endif + +GTM_ASSUME_NONNULL_BEGIN + +// Notifications +// +// Fetch started and stopped, and fetch retry delay started and stopped. +extern NSString *const kGTMSessionFetcherStartedNotification; +extern NSString *const kGTMSessionFetcherStoppedNotification; +extern NSString *const kGTMSessionFetcherRetryDelayStartedNotification; +extern NSString *const kGTMSessionFetcherRetryDelayStoppedNotification; + +// Completion handler notification. This is intended for use by code capturing +// and replaying fetch requests and results for testing. For fetches where +// destinationFileURL or accumulateDataBlock is set for the fetcher, the data +// will be nil for successful fetches. +// +// This notification is posted on the main thread. +extern NSString *const kGTMSessionFetcherCompletionInvokedNotification; +extern NSString *const kGTMSessionFetcherCompletionDataKey; +extern NSString *const kGTMSessionFetcherCompletionErrorKey; + +// Constants for NSErrors created by the fetcher (excluding server status errors, +// and error objects originating in the OS.) +extern NSString *const kGTMSessionFetcherErrorDomain; + +// The fetcher turns server error status values (3XX, 4XX, 5XX) into NSErrors +// with domain kGTMSessionFetcherStatusDomain. +// +// Any server response body data accompanying the status error is added to the +// userInfo dictionary with key kGTMSessionFetcherStatusDataKey. +extern NSString *const kGTMSessionFetcherStatusDomain; +extern NSString *const kGTMSessionFetcherStatusDataKey; +extern NSString *const kGTMSessionFetcherStatusDataContentTypeKey; + +// When a fetch fails with an error, these keys are included in the error userInfo +// dictionary if retries were attempted. +extern NSString *const kGTMSessionFetcherNumberOfRetriesDoneKey; +extern NSString *const kGTMSessionFetcherElapsedIntervalWithRetriesKey; + +// Background session support requires access to NSUserDefaults. +// If [NSUserDefaults standardUserDefaults] doesn't yield the correct NSUserDefaults for your usage, +// ie for an App Extension, then implement this class/method to return the correct NSUserDefaults. +// https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW6 +@interface GTMSessionFetcherUserDefaultsFactory : NSObject + ++ (NSUserDefaults *)fetcherUserDefaults; + +@end + +#ifdef __cplusplus +} +#endif + +typedef NS_ENUM(NSInteger, GTMSessionFetcherError) { + GTMSessionFetcherErrorDownloadFailed = -1, + GTMSessionFetcherErrorUploadChunkUnavailable = -2, + GTMSessionFetcherErrorBackgroundExpiration = -3, + GTMSessionFetcherErrorBackgroundFetchFailed = -4, + GTMSessionFetcherErrorInsecureRequest = -5, + GTMSessionFetcherErrorTaskCreationFailed = -6, +}; + +typedef NS_ENUM(NSInteger, GTMSessionFetcherStatus) { + // Standard http status codes. + GTMSessionFetcherStatusNotModified = 304, + GTMSessionFetcherStatusBadRequest = 400, + GTMSessionFetcherStatusUnauthorized = 401, + GTMSessionFetcherStatusForbidden = 403, + GTMSessionFetcherStatusPreconditionFailed = 412 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +@class GTMSessionCookieStorage; +@class GTMSessionFetcher; + +// The configuration block is for modifying the NSURLSessionConfiguration only. +// DO NOT change any fetcher properties in the configuration block. +typedef void (^GTMSessionFetcherConfigurationBlock)(GTMSessionFetcher *fetcher, + NSURLSessionConfiguration *configuration); +typedef void (^GTMSessionFetcherSystemCompletionHandler)(void); +typedef void (^GTMSessionFetcherCompletionHandler)(NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); +typedef void (^GTMSessionFetcherBodyStreamProviderResponse)(NSInputStream *bodyStream); +typedef void (^GTMSessionFetcherBodyStreamProvider)(GTMSessionFetcherBodyStreamProviderResponse response); +typedef void (^GTMSessionFetcherDidReceiveResponseDispositionBlock)(NSURLSessionResponseDisposition disposition); +typedef void (^GTMSessionFetcherDidReceiveResponseBlock)(NSURLResponse *response, + GTMSessionFetcherDidReceiveResponseDispositionBlock dispositionBlock); +typedef void (^GTMSessionFetcherChallengeDispositionBlock)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential); +typedef void (^GTMSessionFetcherChallengeBlock)(GTMSessionFetcher *fetcher, + NSURLAuthenticationChallenge *challenge, + GTMSessionFetcherChallengeDispositionBlock dispositionBlock); +typedef void (^GTMSessionFetcherWillRedirectResponse)(NSURLRequest * GTM_NULLABLE_TYPE redirectedRequest); +typedef void (^GTMSessionFetcherWillRedirectBlock)(NSHTTPURLResponse *redirectResponse, + NSURLRequest *redirectRequest, + GTMSessionFetcherWillRedirectResponse response); +typedef void (^GTMSessionFetcherAccumulateDataBlock)(NSData * GTM_NULLABLE_TYPE buffer); +typedef void (^GTMSessionFetcherSimulateByteTransferBlock)(NSData * GTM_NULLABLE_TYPE buffer, + int64_t bytesWritten, + int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite); +typedef void (^GTMSessionFetcherReceivedProgressBlock)(int64_t bytesWritten, + int64_t totalBytesWritten); +typedef void (^GTMSessionFetcherDownloadProgressBlock)(int64_t bytesWritten, + int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite); +typedef void (^GTMSessionFetcherSendProgressBlock)(int64_t bytesSent, + int64_t totalBytesSent, + int64_t totalBytesExpectedToSend); +typedef void (^GTMSessionFetcherWillCacheURLResponseResponse)(NSCachedURLResponse * GTM_NULLABLE_TYPE cachedResponse); +typedef void (^GTMSessionFetcherWillCacheURLResponseBlock)(NSCachedURLResponse *proposedResponse, + GTMSessionFetcherWillCacheURLResponseResponse responseBlock); +typedef void (^GTMSessionFetcherRetryResponse)(BOOL shouldRetry); +typedef void (^GTMSessionFetcherRetryBlock)(BOOL suggestedWillRetry, + NSError * GTM_NULLABLE_TYPE error, + GTMSessionFetcherRetryResponse response); + +API_AVAILABLE(ios(10.0), macosx(10.12), tvos(10.0), watchos(3.0)) +typedef void (^GTMSessionFetcherMetricsCollectionBlock)(NSURLSessionTaskMetrics *metrics); + +typedef void (^GTMSessionFetcherTestResponse)(NSHTTPURLResponse * GTM_NULLABLE_TYPE response, + NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); +typedef void (^GTMSessionFetcherTestBlock)(GTMSessionFetcher *fetcherToTest, + GTMSessionFetcherTestResponse testResponse); + +void GTMSessionFetcherAssertValidSelector(id GTM_NULLABLE_TYPE obj, SEL GTM_NULLABLE_TYPE sel, ...); + +// Utility functions for applications self-identifying to servers via a +// user-agent header + +// The "standard" user agent includes the application identifier, taken from the bundle, +// followed by a space and the system version string. Pass nil to use +mainBundle as the source +// of the bundle identifier. +// +// Applications may use this as a starting point for their own user agent strings, perhaps +// with additional sections appended. Use GTMFetcherCleanedUserAgentString() below to +// clean up any string being added to the user agent. +NSString *GTMFetcherStandardUserAgentString(NSBundle * GTM_NULLABLE_TYPE bundle); + +// Make a generic name and version for the current application, like +// com.example.MyApp/1.2.3 relying on the bundle identifier and the +// CFBundleShortVersionString or CFBundleVersion. +// +// The bundle ID may be overridden as the base identifier string by +// adding to the bundle's Info.plist a "GTMUserAgentID" key. +// +// If no bundle ID or override is available, the process name preceded +// by "proc_" is used. +NSString *GTMFetcherApplicationIdentifier(NSBundle * GTM_NULLABLE_TYPE bundle); + +// Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1 hw/iPod1_1" +NSString *GTMFetcherSystemVersionString(void); + +// Make a parseable user-agent identifier from the given string, replacing whitespace +// and commas with underscores, and removing other characters that may interfere +// with parsing of the full user-agent string. +// +// For example, @"[My App]" would become @"My_App" +NSString *GTMFetcherCleanedUserAgentString(NSString *str); + +// Grab the data from an input stream. Since streams cannot be assumed to be rewindable, +// this may be destructive; the caller can try to rewind the stream (by setting the +// NSStreamFileCurrentOffsetKey property) or can just use the NSData to make a new +// NSInputStream. This function is intended to facilitate testing rather than be used in +// production. +// +// This function operates synchronously on the current thread. Depending on how the +// input stream is implemented, it may be appropriate to dispatch to a different +// queue before calling this function. +// +// Failure is indicated by a returned data value of nil. +NSData * GTM_NULLABLE_TYPE GTMDataFromInputStream(NSInputStream *inputStream, NSError **outError); + +#ifdef __cplusplus +} // extern "C" +#endif + + +#if !GTM_USE_SESSION_FETCHER +@protocol GTMHTTPFetcherServiceProtocol; +#endif + +// This protocol allows abstract references to the fetcher service, primarily for +// fetchers (which may be compiled without the fetcher service class present.) +// +// Apps should not need to use this protocol. +@protocol GTMSessionFetcherServiceProtocol +// This protocol allows us to call into the service without requiring +// GTMSessionFetcherService sources in this project + +@property(atomic, strong) dispatch_queue_t callbackQueue; + +- (BOOL)fetcherShouldBeginFetching:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidCreateSession:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidBeginFetching:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidStop:(GTMSessionFetcher *)fetcher; + +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher; + +@property(atomic, assign) BOOL reuseSession; +- (GTM_NULLABLE NSURLSession *)session; +- (GTM_NULLABLE NSURLSession *)sessionForFetcherCreation; +- (GTM_NULLABLE id)sessionDelegate; +- (GTM_NULLABLE NSDate *)stoppedAllFetchersDate; + +// Methods for compatibility with the old GTMHTTPFetcher. +@property(atomic, readonly, strong, GTM_NULLABLE) NSOperationQueue *delegateQueue; + +@end // @protocol GTMSessionFetcherServiceProtocol + +#ifndef GTM_FETCHER_AUTHORIZATION_PROTOCOL +#define GTM_FETCHER_AUTHORIZATION_PROTOCOL 1 +@protocol GTMFetcherAuthorizationProtocol +@required +// This protocol allows us to call the authorizer without requiring its sources +// in this project. +- (void)authorizeRequest:(GTM_NULLABLE NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel; + +- (void)stopAuthorization; + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request; + +@property(atomic, strong, readonly, GTM_NULLABLE) NSString *userEmail; + +@optional + +// Indicate if authorization may be attempted. Even if this succeeds, +// authorization may fail if the user's permissions have been revoked. +@property(atomic, readonly) BOOL canAuthorize; + +// For development only, allow authorization of non-SSL requests, allowing +// transmission of the bearer token unencrypted. +@property(atomic, assign) BOOL shouldAuthorizeAllRequests; + +- (void)authorizeRequest:(GTM_NULLABLE NSMutableURLRequest *)request + completionHandler:(void (^)(NSError * GTM_NULLABLE_TYPE error))handler; + +#if GTM_USE_SESSION_FETCHER +@property(atomic, weak, GTM_NULLABLE) id fetcherService; +#else +@property(atomic, weak, GTM_NULLABLE) id fetcherService; +#endif + +- (BOOL)primeForRefresh; + +@end +#endif // GTM_FETCHER_AUTHORIZATION_PROTOCOL + +#if GTM_BACKGROUND_TASK_FETCHING +// A protocol for an alternative target for messages from GTMSessionFetcher to UIApplication. +// Set the target using +[GTMSessionFetcher setSubstituteUIApplication:] +@protocol GTMUIApplicationProtocol +- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName + expirationHandler:(void(^ __nullable)(void))handler; +- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier; +@end +#endif + +#pragma mark - + +// GTMSessionFetcher objects are used for async retrieval of an http get or post +// +// See additional comments at the beginning of this file +@interface GTMSessionFetcher : NSObject + +// Create a fetcher +// +// fetcherWithRequest will return an autoreleased fetcher, but if +// the connection is successfully created, the connection should retain the +// fetcher for the life of the connection as well. So the caller doesn't have +// to retain the fetcher explicitly unless they want to be able to cancel it. ++ (instancetype)fetcherWithRequest:(GTM_NULLABLE NSURLRequest *)request; + +// Convenience methods that make a request, like +fetcherWithRequest ++ (instancetype)fetcherWithURL:(NSURL *)requestURL; ++ (instancetype)fetcherWithURLString:(NSString *)requestURLString; + +// Methods for creating fetchers to continue previous fetches. ++ (instancetype)fetcherWithDownloadResumeData:(NSData *)resumeData; ++ (GTM_NULLABLE instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier; + +// Returns an array of currently active fetchers for background sessions, +// both restarted and newly created ones. ++ (GTM_NSArrayOf(GTMSessionFetcher *) *)fetchersForBackgroundSessions; + +// Designated initializer. +// +// Applications should create fetchers with a "fetcherWith..." method on a fetcher +// service or a class method, not with this initializer. +// +// The configuration should typically be nil. Applications needing to customize +// the configuration may do so by setting the configurationBlock property. +- (instancetype)initWithRequest:(GTM_NULLABLE NSURLRequest *)request + configuration:(GTM_NULLABLE NSURLSessionConfiguration *)configuration; + +// The fetcher's request. This may not be set after beginFetch has been invoked. The request +// may change due to redirects. +@property(atomic, strong, GTM_NULLABLE) NSURLRequest *request; + +// Set a header field value on the request. Header field value changes will not +// affect a fetch after the fetch has begun. +- (void)setRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field; + +// Data used for resuming a download task. +@property(atomic, readonly, GTM_NULLABLE) NSData *downloadResumeData; + +// The configuration; this must be set before the fetch begins. If no configuration is +// set or inherited from the fetcher service, then the fetcher uses an ephemeral config. +// +// NOTE: This property should typically be nil. Applications needing to customize +// the configuration should do so by setting the configurationBlock property. +// That allows the fetcher to pick an appropriate base configuration, with the +// application setting only the configuration properties it needs to customize. +@property(atomic, strong, GTM_NULLABLE) NSURLSessionConfiguration *configuration; + +// A block the client may use to customize the configuration used to create the session. +// +// This is called synchronously, either on the thread that begins the fetch or, during a retry, +// on the main thread. The configuration block may be called repeatedly if multiple fetchers are +// created. +// +// The configuration block is for modifying the NSURLSessionConfiguration only. +// DO NOT change any fetcher properties in the configuration block. Fetcher properties +// may be set in the fetcher service prior to fetcher creation, or on the fetcher prior +// to invoking beginFetch. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherConfigurationBlock configurationBlock; + +// A session is created as needed by the fetcher. A fetcher service object +// may maintain sessions for multiple fetches to the same host. +@property(atomic, strong, GTM_NULLABLE) NSURLSession *session; + +// The task in flight. +@property(atomic, readonly, GTM_NULLABLE) NSURLSessionTask *sessionTask; + +// The background session identifier. +@property(atomic, readonly, GTM_NULLABLE) NSString *sessionIdentifier; + +// Indicates a fetcher created to finish a background session task. +@property(atomic, readonly) BOOL wasCreatedFromBackgroundSession; + +// Additional user-supplied data to encode into the session identifier. Since session identifier +// length limits are unspecified, this should be kept small. Key names beginning with an underscore +// are reserved for use by the fetcher. +@property(atomic, strong, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSString *) *sessionUserInfo; + +// The human-readable description to be assigned to the task. +@property(atomic, copy, GTM_NULLABLE) NSString *taskDescription; + +// The priority assigned to the task, if any. Use NSURLSessionTaskPriorityLow, +// NSURLSessionTaskPriorityDefault, or NSURLSessionTaskPriorityHigh. +@property(atomic, assign) float taskPriority; + +// The fetcher encodes information used to resume a session in the session identifier. +// This method, intended for internal use returns the encoded information. The sessionUserInfo +// dictionary is stored as identifier metadata. +- (GTM_NULLABLE GTM_NSDictionaryOf(NSString *, NSString *) *)sessionIdentifierMetadata; + +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH +// The app should pass to this method the completion handler passed in the app delegate method +// application:handleEventsForBackgroundURLSession:completionHandler: ++ (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(GTMSessionFetcherSystemCompletionHandler)completionHandler; +#endif + +// Indicate that a newly created session should be a background session. +// A new session identifier will be created by the fetcher. +// +// Warning: The only thing background sessions are for is rare download +// of huge, batched files of data. And even just for those, there's a lot +// of pain and hackery needed to get transfers to actually happen reliably +// with background sessions. +// +// Don't try to upload or download in many background sessions, since the system +// will impose an exponentially increasing time penalty to prevent the app from +// getting too much background execution time. +// +// References: +// +// "Moving to Fewer, Larger Transfers" +// https://forums.developer.apple.com/thread/14853 +// +// "NSURLSession’s Resume Rate Limiter" +// https://forums.developer.apple.com/thread/14854 +// +// "Background Session Task state persistence" +// https://forums.developer.apple.com/thread/11554 +// +@property(atomic, assign) BOOL useBackgroundSession; + +// Indicates if the fetcher was started using a background session. +@property(atomic, readonly, getter=isUsingBackgroundSession) BOOL usingBackgroundSession; + +// Indicates if uploads should use an upload task. This is always set for file or stream-provider +// bodies, but may be set explicitly for NSData bodies. +@property(atomic, assign) BOOL useUploadTask; + +// Indicates that the fetcher is using a session that may be shared with other fetchers. +@property(atomic, readonly) BOOL canShareSession; + +// By default, the fetcher allows only secure (https) schemes unless this +// property is set, or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For example, during debugging when fetching from a development server that lacks SSL support, +// this may be set to @[ @"http" ], or when the fetcher is used to retrieve local files, +// this may be set to @[ @"file" ]. +// +// This should be left as nil for release builds to avoid creating the opportunity for +// leaking private user behavior and data. If a server is providing insecure URLs +// for fetching by the client app, report the problem as server security & privacy bug. +// +// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when +// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist. +@property(atomic, copy, GTM_NULLABLE) GTM_NSArrayOf(NSString *) *allowedInsecureSchemes; + +// By default, the fetcher prohibits localhost requests unless this property is set, +// or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For localhost requests, the URL scheme is not checked when this property is set. +// +// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when +// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist. +@property(atomic, assign) BOOL allowLocalhostRequest; + +// By default, the fetcher requires valid server certs. This may be bypassed +// temporarily for development against a test server with an invalid cert. +@property(atomic, assign) BOOL allowInvalidServerCertificates; + +// Cookie storage object for this fetcher. If nil, the fetcher will use a static cookie +// storage instance shared among fetchers. If this fetcher was created by a fetcher service +// object, it will be set to use the service object's cookie storage. See Cookies section above for +// the full discussion. +// +// Because as of Jan 2014 standalone instances of NSHTTPCookieStorage do not actually +// store any cookies (Radar 15735276) we use our own subclass, GTMSessionCookieStorage, +// to hold cookies in memory. +@property(atomic, strong, GTM_NULLABLE) NSHTTPCookieStorage *cookieStorage; + +// Setting the credential is optional; it is used if the connection receives +// an authentication challenge. +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *credential; + +// Setting the proxy credential is optional; it is used if the connection +// receives an authentication challenge from a proxy. +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *proxyCredential; + +// If body data, body file URL, or body stream provider is not set, then a GET request +// method is assumed. +@property(atomic, strong, GTM_NULLABLE) NSData *bodyData; + +// File to use as the request body. This forces use of an upload task. +@property(atomic, strong, GTM_NULLABLE) NSURL *bodyFileURL; + +// Length of body to send, expected or actual. +@property(atomic, readonly) int64_t bodyLength; + +// The body stream provider may be called repeatedly to provide a body. +// Setting a body stream provider forces use of an upload task. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherBodyStreamProvider bodyStreamProvider; + +// Object to add authorization to the request, if needed. +// +// This may not be changed once beginFetch has been invoked. +@property(atomic, strong, GTM_NULLABLE) id authorizer; + +// The service object that created and monitors this fetcher, if any. +@property(atomic, strong) id service; + +// The host, if any, used to classify this fetcher in the fetcher service. +@property(atomic, copy, GTM_NULLABLE) NSString *serviceHost; + +// The priority, if any, used for starting fetchers in the fetcher service. +// +// Lower values are higher priority; the default is 0, and values may +// be negative or positive. This priority affects only the start order of +// fetchers that are being delayed by a fetcher service when the running fetchers +// exceeds the service's maxRunningFetchersPerHost. A priority of NSIntegerMin will +// exempt this fetcher from delay. +@property(atomic, assign) NSInteger servicePriority; + +// The delegate's optional didReceiveResponse block may be used to inspect or alter +// the session task response. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherDidReceiveResponseBlock didReceiveResponseBlock; + +// The delegate's optional challenge block may be used to inspect or alter +// the session task challenge. +// +// If this block is not set, the fetcher's default behavior for the NSURLSessionTask +// didReceiveChallenge: delegate method is to use the fetcher's respondToChallenge: method +// which relies on the fetcher's credential and proxyCredential properties. +// +// Warning: This may be called repeatedly if the challenge fails. Check +// challenge.previousFailureCount to identify repeated invocations. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherChallengeBlock challengeBlock; + +// The delegate's optional willRedirect block may be used to inspect or alter +// the redirection. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherWillRedirectBlock willRedirectBlock; + +// The optional send progress block reports body bytes uploaded. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherSendProgressBlock sendProgressBlock; + +// The optional accumulate block may be set by clients wishing to accumulate data +// themselves rather than let the fetcher append each buffer to an NSData. +// +// When this is called with nil data (such as on redirect) the client +// should empty its accumulation buffer. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherAccumulateDataBlock accumulateDataBlock; + +// The optional received progress block may be used to monitor data +// received from a data task. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherReceivedProgressBlock receivedProgressBlock; + +// The delegate's optional downloadProgress block may be used to monitor download +// progress in writing to disk. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherDownloadProgressBlock downloadProgressBlock; + +// The delegate's optional willCacheURLResponse block may be used to alter the cached +// NSURLResponse. The user may prevent caching by passing nil to the block's response. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherWillCacheURLResponseBlock willCacheURLResponseBlock; + +// Enable retrying; see comments at the top of this file. Setting +// retryEnabled=YES resets the min and max retry intervals. +@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled; + +// Retry block is optional for retries. +// +// If present, this block should call the response block with YES to cause a retry or NO to end the +// fetch. +// See comments at the top of this file. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherRetryBlock retryBlock; + +// The optional block for collecting the metrics of the present session. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) + GTMSessionFetcherMetricsCollectionBlock metricsCollectionBlock API_AVAILABLE( + ios(10.0), macosx(10.12), tvos(10.0), watchos(3.0)); + +// Retry intervals must be strictly less than maxRetryInterval, else +// they will be limited to maxRetryInterval and no further retries will +// be attempted. Setting maxRetryInterval to 0.0 will reset it to the +// default value, 60 seconds for downloads and 600 seconds for uploads. +@property(atomic, assign) NSTimeInterval maxRetryInterval; + +// Starting retry interval. Setting minRetryInterval to 0.0 will reset it +// to a random value between 1.0 and 2.0 seconds. Clients should normally not +// set this except for unit testing. +@property(atomic, assign) NSTimeInterval minRetryInterval; + +// Multiplier used to increase the interval between retries, typically 2.0. +// Clients should not need to set this. +@property(atomic, assign) double retryFactor; + +// Number of retries attempted. +@property(atomic, readonly) NSUInteger retryCount; + +// Interval delay to precede next retry. +@property(atomic, readonly) NSTimeInterval nextRetryInterval; + +#if GTM_BACKGROUND_TASK_FETCHING +// Skip use of a UIBackgroundTask, thus requiring fetches to complete when the app is in the +// foreground. +// +// Targets should define GTM_BACKGROUND_TASK_FETCHING to 0 to avoid use of a UIBackgroundTask +// on iOS to allow fetches to complete in the background. This property is available when +// it's not practical to set the preprocessor define. +@property(atomic, assign) BOOL skipBackgroundTask; +#endif // GTM_BACKGROUND_TASK_FETCHING + +// Begin fetching the request +// +// The delegate may optionally implement the callback or pass nil for the selector or handler. +// +// The delegate and all callback blocks are retained between the beginFetch call until after the +// finish callback, or until the fetch is stopped. +// +// An error is passed to the callback for server statuses 300 or +// higher, with the status stored as the error object's code. +// +// finishedSEL has a signature like: +// - (void)fetcher:(GTMSessionFetcher *)fetcher +// finishedWithData:(NSData *)data +// error:(NSError *)error; +// +// If the application has specified a destinationFileURL or an accumulateDataBlock +// for the fetcher, the data parameter passed to the callback will be nil. + +- (void)beginFetchWithDelegate:(GTM_NULLABLE id)delegate + didFinishSelector:(GTM_NULLABLE SEL)finishedSEL; + +- (void)beginFetchWithCompletionHandler:(GTM_NULLABLE GTMSessionFetcherCompletionHandler)handler; + +// Returns YES if this fetcher is in the process of fetching a URL. +@property(atomic, readonly, getter=isFetching) BOOL fetching; + +// Cancel the fetch of the request that's currently in progress. The completion handler +// will not be called. +- (void)stopFetching; + +// A block to be called when the fetch completes. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherCompletionHandler completionHandler; + +// A block to be called if download resume data becomes available. +@property(atomic, strong, GTM_NULLABLE) void (^resumeDataBlock)(NSData *); + +// Return the status code from the server response. +@property(atomic, readonly) NSInteger statusCode; + +// Return the http headers from the response. +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSString *) *responseHeaders; + +// The response, once it's been received. +@property(atomic, strong, readonly, GTM_NULLABLE) NSURLResponse *response; + +// Bytes downloaded so far. +@property(atomic, readonly) int64_t downloadedLength; + +// Buffer of currently-downloaded data, if available. +@property(atomic, readonly, strong, GTM_NULLABLE) NSData *downloadedData; + +// Local path to which the downloaded file will be moved. +// +// If a file already exists at the path, it will be overwritten. +// Will create the enclosing folders if they are not present. +@property(atomic, strong, GTM_NULLABLE) NSURL *destinationFileURL; + +// The time this fetcher originally began fetching. This is useful as a time +// barrier for ignoring irrelevant fetch notifications or callbacks. +@property(atomic, strong, readonly, GTM_NULLABLE) NSDate *initialBeginFetchDate; + +// userData is retained solely for the convenience of the client. +@property(atomic, strong, GTM_NULLABLE) id userData; + +// Stored property values are retained solely for the convenience of the client. +@property(atomic, copy, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, id) *properties; + +- (void)setProperty:(GTM_NULLABLE id)obj forKey:(NSString *)key; // Pass nil for obj to remove the property. +- (GTM_NULLABLE id)propertyForKey:(NSString *)key; + +- (void)addPropertiesFromDictionary:(GTM_NSDictionaryOf(NSString *, id) *)dict; + +// Comments are useful for logging, so are strongly recommended for each fetcher. +@property(atomic, copy, GTM_NULLABLE) NSString *comment; + +- (void)setCommentWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +// Log of request and response, if logging is enabled +@property(atomic, copy, GTM_NULLABLE) NSString *log; + +// Callbacks are run on this queue. If none is supplied, the main queue is used. +@property(atomic, strong, GTM_NULL_RESETTABLE) dispatch_queue_t callbackQueue; + +// The queue used internally by the session to invoke its delegate methods in the fetcher. +// +// Application callbacks are always called by the fetcher on the callbackQueue above, +// not on this queue. Apps should generally not change this queue. +// +// The default delegate queue is the main queue. +// +// This value is ignored after the session has been created, so this +// property should be set in the fetcher service rather in the fetcher as it applies +// to a shared session. +@property(atomic, strong, GTM_NULL_RESETTABLE) NSOperationQueue *sessionDelegateQueue; + +// Spin the run loop or sleep the thread, discarding events, until the fetch has completed. +// +// This is only for use in testing or in tools without a user interface. +// +// Note: Synchronous fetches should never be used by shipping apps; they are +// sufficient reason for rejection from the app store. +// +// Returns NO if timed out. +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds; + +// Test block is optional for testing. +// +// If present, this block will cause the fetcher to skip starting the session, and instead +// use the test block response values when calling the completion handler and delegate code. +// +// Test code can set this on the fetcher or on the fetcher service. For testing libraries +// that use a fetcher without exposing either the fetcher or the fetcher service, the global +// method setGlobalTestBlock: will set the block for all fetchers that do not have a test +// block set. +// +// The test code can pass nil for all response parameters to indicate that the fetch +// should proceed. +// +// Applications can exclude test block support by setting GTM_DISABLE_FETCHER_TEST_BLOCK. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherTestBlock testBlock; + ++ (void)setGlobalTestBlock:(GTM_NULLABLE GTMSessionFetcherTestBlock)block; + +// When using the testBlock, |testBlockAccumulateDataChunkCount| is the desired number of chunks to +// divide the response data into if the client has streaming enabled. The data will be divided up to +// |testBlockAccumulateDataChunkCount| chunks; however, the exact amount may vary depending on the +// size of the response data (e.g. a 1-byte response can only be divided into one chunk). +@property(atomic, readwrite) NSUInteger testBlockAccumulateDataChunkCount; + +#if GTM_BACKGROUND_TASK_FETCHING +// For testing or to override UIApplication invocations, apps may specify an alternative +// target for messages to UIApplication. ++ (void)setSubstituteUIApplication:(nullable id)substituteUIApplication; ++ (nullable id)substituteUIApplication; +#endif // GTM_BACKGROUND_TASK_FETCHING + +// Exposed for testing. ++ (GTMSessionCookieStorage *)staticCookieStorage; ++ (BOOL)appAllowsInsecureRequests; + +#if STRIP_GTM_FETCH_LOGGING +// If logging is stripped, provide a stub for the main method +// for controlling logging. ++ (void)setLoggingEnabled:(BOOL)flag; ++ (BOOL)isLoggingEnabled; + +#else + +// These methods let an application log specific body text, such as the text description of a binary +// request or response. The application should set the fetcher to defer response body logging until +// the response has been received and the log response body has been set by the app. For example: +// +// fetcher.logRequestBody = [binaryObject stringDescription]; +// fetcher.deferResponseBodyLogging = YES; +// [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { +// if (error == nil) { +// fetcher.logResponseBody = [[[MyThing alloc] initWithData:data] stringDescription]; +// } +// fetcher.deferResponseBodyLogging = NO; +// }]; + +@property(atomic, copy, GTM_NULLABLE) NSString *logRequestBody; +@property(atomic, assign) BOOL deferResponseBodyLogging; +@property(atomic, copy, GTM_NULLABLE) NSString *logResponseBody; + +// Internal logging support. +@property(atomic, readonly) NSData *loggedStreamData; +@property(atomic, assign) BOOL hasLoggedError; +@property(atomic, strong, GTM_NULLABLE) NSURL *redirectedFromURL; +- (void)appendLoggedStreamData:(NSData *)dataToAdd; +- (void)clearLoggedStreamData; + +#endif // STRIP_GTM_FETCH_LOGGING + +@end + +@interface GTMSessionFetcher (BackwardsCompatibilityOnly) +// Clients using GTMSessionFetcher should set the cookie storage explicitly themselves. +// This method is just for compatibility with the old GTMHTTPFetcher class. +- (void)setCookieStorageMethod:(NSInteger)method; +@end + +// Until we can just instantiate NSHTTPCookieStorage for local use, we'll +// implement all the public methods ourselves. This stores cookies only in +// memory. Additional methods are provided for testing. +// +// iOS 9/OS X 10.11 added +[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:] +// which may also be used to create cookie storage. +@interface GTMSessionCookieStorage : NSHTTPCookieStorage + +// Add the array off cookies to the storage, replacing duplicates. +// Also removes expired cookies from the storage. +- (void)setCookies:(GTM_NULLABLE GTM_NSArrayOf(NSHTTPCookie *) *)cookies; + +- (void)removeAllCookies; + +@end + +// Macros to monitor synchronization blocks in debug builds. +// These report problems using GTMSessionCheckDebug. +// +// GTMSessionMonitorSynchronized Start monitoring a top-level-only +// @sync scope. +// GTMSessionMonitorRecursiveSynchronized Start monitoring a top-level or +// recursive @sync scope. +// GTMSessionCheckSynchronized Verify that the current execution +// is inside a @sync scope. +// GTMSessionCheckNotSynchronized Verify that the current execution +// is not inside a @sync scope. +// +// Example usage: +// +// - (void)myExternalMethod { +// @synchronized(self) { +// GTMSessionMonitorSynchronized(self) +// +// - (void)myInternalMethod { +// GTMSessionCheckSynchronized(self); +// +// - (void)callMyCallbacks { +// GTMSessionCheckNotSynchronized(self); +// +// GTMSessionCheckNotSynchronized is available for verifying the code isn't +// in a deadlockable @sync state when posting notifications and invoking +// callbacks. Don't use GTMSessionCheckNotSynchronized immediately before a +// @sync scope; the normal recursiveness check of GTMSessionMonitorSynchronized +// can catch those. + +#ifdef __OBJC__ +// If asserts are entirely no-ops, the synchronization monitor is just a bunch +// of counting code that doesn't report exceptional circumstances in any way. +// Only build the synchronization monitor code if NS_BLOCK_ASSERTIONS is not +// defined or asserts are being logged instead. +#if DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) + #define __GTMSessionMonitorSynchronizedVariableInner(varname, counter) \ + varname ## counter + #define __GTMSessionMonitorSynchronizedVariable(varname, counter) \ + __GTMSessionMonitorSynchronizedVariableInner(varname, counter) + + #define GTMSessionMonitorSynchronized(obj) \ + NS_VALID_UNTIL_END_OF_SCOPE id \ + __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \ + [[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \ + allowRecursive:NO \ + functionName:__func__] + + #define GTMSessionMonitorRecursiveSynchronized(obj) \ + NS_VALID_UNTIL_END_OF_SCOPE id \ + __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \ + [[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \ + allowRecursive:YES \ + functionName:__func__] + + #define GTMSessionCheckSynchronized(obj) { \ + GTMSESSION_ASSERT_DEBUG( \ + [GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + @"GTMSessionCheckSynchronized(" #obj ") failed: not sync'd" \ + @" on " #obj " in %s. Call stack:\n%@", \ + __func__, [NSThread callStackSymbols]); \ + } + + #define GTMSessionCheckNotSynchronized(obj) { \ + GTMSESSION_ASSERT_DEBUG( \ + ![GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + @"GTMSessionCheckNotSynchronized(" #obj ") failed: was sync'd" \ + @" on " #obj " in %s by %@. Call stack:\n%@", __func__, \ + [GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + [NSThread callStackSymbols]); \ + } + +// GTMSessionSyncMonitorInternal is a private class that keeps track of the +// beginning and end of synchronized scopes. +// +// This class should not be used directly, but only via the +// GTMSessionMonitorSynchronized macro. +@interface GTMSessionSyncMonitorInternal : NSObject +- (instancetype)initWithSynchronizationObject:(id)object + allowRecursive:(BOOL)allowRecursive + functionName:(const char *)functionName; +// Return the names of the functions that hold sync on the object, or nil if none. ++ (NSArray *)functionsHoldingSynchronizationOnObject:(id)object; +@end + +#else + #define GTMSessionMonitorSynchronized(obj) do { } while (0) + #define GTMSessionMonitorRecursiveSynchronized(obj) do { } while (0) + #define GTMSessionCheckSynchronized(obj) do { } while (0) + #define GTMSessionCheckNotSynchronized(obj) do { } while (0) +#endif // !DEBUG +#endif // __OBJC__ + + +GTM_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m new file mode 100644 index 00000000..3dc64597 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m @@ -0,0 +1,4670 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionFetcher.h" +#if TARGET_OS_OSX && GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH +// To reconnect background sessions on Mac outside +load requires importing and linking +// AppKit to access the NSApplicationDidFinishLaunching symbol. +#import +#endif + +#import + +#ifndef STRIP_GTM_FETCH_LOGGING + #error GTMSessionFetcher headers should have defaulted this if it wasn't already defined. +#endif + +GTM_ASSUME_NONNULL_BEGIN + +NSString *const kGTMSessionFetcherStartedNotification = @"kGTMSessionFetcherStartedNotification"; +NSString *const kGTMSessionFetcherStoppedNotification = @"kGTMSessionFetcherStoppedNotification"; +NSString *const kGTMSessionFetcherRetryDelayStartedNotification = @"kGTMSessionFetcherRetryDelayStartedNotification"; +NSString *const kGTMSessionFetcherRetryDelayStoppedNotification = @"kGTMSessionFetcherRetryDelayStoppedNotification"; + +NSString *const kGTMSessionFetcherCompletionInvokedNotification = @"kGTMSessionFetcherCompletionInvokedNotification"; +NSString *const kGTMSessionFetcherCompletionDataKey = @"data"; +NSString *const kGTMSessionFetcherCompletionErrorKey = @"error"; + +NSString *const kGTMSessionFetcherErrorDomain = @"com.google.GTMSessionFetcher"; +NSString *const kGTMSessionFetcherStatusDomain = @"com.google.HTTPStatus"; +NSString *const kGTMSessionFetcherStatusDataKey = @"data"; // data returned with a kGTMSessionFetcherStatusDomain error +NSString *const kGTMSessionFetcherStatusDataContentTypeKey = @"data_content_type"; + +NSString *const kGTMSessionFetcherNumberOfRetriesDoneKey = @"kGTMSessionFetcherNumberOfRetriesDoneKey"; +NSString *const kGTMSessionFetcherElapsedIntervalWithRetriesKey = @"kGTMSessionFetcherElapsedIntervalWithRetriesKey"; + +static NSString *const kGTMSessionIdentifierPrefix = @"com.google.GTMSessionFetcher"; +static NSString *const kGTMSessionIdentifierDestinationFileURLMetadataKey = @"_destURL"; +static NSString *const kGTMSessionIdentifierBodyFileURLMetadataKey = @"_bodyURL"; + +// The default max retry interview is 10 minutes for uploads (POST/PUT/PATCH), +// 1 minute for downloads. +static const NSTimeInterval kUnsetMaxRetryInterval = -1.0; +static const NSTimeInterval kDefaultMaxDownloadRetryInterval = 60.0; +static const NSTimeInterval kDefaultMaxUploadRetryInterval = 60.0 * 10.; + +// The maximum data length that can be loaded to the error userInfo +static const int64_t kMaximumDownloadErrorDataLength = 20000; + +#ifdef GTMSESSION_PERSISTED_DESTINATION_KEY +// Projects using unique class names should also define a unique persisted destination key. +static NSString * const kGTMSessionFetcherPersistedDestinationKey = + GTMSESSION_PERSISTED_DESTINATION_KEY; +#else +static NSString * const kGTMSessionFetcherPersistedDestinationKey = + @"com.google.GTMSessionFetcher.downloads"; +#endif + +GTM_ASSUME_NONNULL_END + +// +// GTMSessionFetcher +// + +#if 0 +#define GTM_LOG_BACKGROUND_SESSION(...) GTMSESSION_LOG_DEBUG(__VA_ARGS__) +#else +#define GTM_LOG_BACKGROUND_SESSION(...) +#endif + +#ifndef GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY + #if (TARGET_OS_TV \ + || TARGET_OS_WATCH \ + || (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0)) + #define GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY 1 + #endif +#endif + +#if ((defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) || \ + (TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MIN_REQUIRED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MIN_REQUIRED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#elif ((TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MAX_ALLOWED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MAX_ALLOWED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#else +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#endif + +#if ((defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) || \ + (TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MIN_REQUIRED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MIN_REQUIRED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR 1 +#else +#define GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR 0 +#endif + +@interface GTMSessionFetcher () + +@property(atomic, strong, readwrite, GTM_NULLABLE) NSData *downloadedData; +@property(atomic, strong, readwrite, GTM_NULLABLE) NSData *downloadResumeData; + +#if GTM_BACKGROUND_TASK_FETCHING +// Should always be accessed within an @synchronized(self). +@property(assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier; +#endif + +@property(atomic, readwrite, getter=isUsingBackgroundSession) BOOL usingBackgroundSession; + +@end + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (GTMSessionFetcherLoggingInternal) +- (void)logFetchWithError:(NSError *)error; +- (void)logNowWithError:(GTM_NULLABLE NSError *)error; +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream; +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider; +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +GTM_ASSUME_NONNULL_BEGIN + +static NSTimeInterval InitialMinRetryInterval(void) { + return 1.0 + ((double)(arc4random_uniform(0x0FFFF)) / (double) 0x0FFFF); +} + +static BOOL IsLocalhost(NSString * GTM_NULLABLE_TYPE host) { + // We check if there's host, and then make the comparisons. + if (host == nil) return NO; + return ([host caseInsensitiveCompare:@"localhost"] == NSOrderedSame + || [host isEqual:@"::1"] + || [host isEqual:@"127.0.0.1"]); +} + +static NSDictionary *GTM_NULLABLE_TYPE GTMErrorUserInfoForData( + NSData *GTM_NULLABLE_TYPE data, NSDictionary *GTM_NULLABLE_TYPE responseHeaders) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + + if (data.length > 0) { + userInfo[kGTMSessionFetcherStatusDataKey] = data; + + NSString *contentType = responseHeaders[@"Content-Type"]; + if (contentType) { + userInfo[kGTMSessionFetcherStatusDataContentTypeKey] = contentType; + } + } + + return userInfo.count > 0 ? userInfo : nil; +} + +static GTMSessionFetcherTestBlock GTM_NULLABLE_TYPE gGlobalTestBlock; + +@implementation GTMSessionFetcher { + NSMutableURLRequest *_request; // after beginFetch, changed only in delegate callbacks + BOOL _useUploadTask; // immutable after beginFetch + NSURL *_bodyFileURL; // immutable after beginFetch + GTMSessionFetcherBodyStreamProvider _bodyStreamProvider; // immutable after beginFetch + NSURLSession *_session; + BOOL _shouldInvalidateSession; // immutable after beginFetch + NSURLSession *_sessionNeedingInvalidation; + NSURLSessionConfiguration *_configuration; + NSURLSessionTask *_sessionTask; + NSString *_taskDescription; + float _taskPriority; + NSURLResponse *_response; + NSString *_sessionIdentifier; + BOOL _wasCreatedFromBackgroundSession; + BOOL _didCreateSessionIdentifier; + NSString *_sessionIdentifierUUID; + BOOL _userRequestedBackgroundSession; + BOOL _usingBackgroundSession; + NSMutableData * GTM_NULLABLE_TYPE _downloadedData; + NSError *_downloadFinishedError; + NSData *_downloadResumeData; // immutable after construction + NSData * GTM_NULLABLE_TYPE _downloadTaskErrorData; // Data for when download task fails + NSURL *_destinationFileURL; + int64_t _downloadedLength; + NSURLCredential *_credential; // username & password + NSURLCredential *_proxyCredential; // credential supplied to proxy servers + BOOL _isStopNotificationNeeded; // set when start notification has been sent + BOOL _isUsingTestBlock; // set when a test block was provided (remains set when the block is released) + id _userData; // retained, if set by caller + NSMutableDictionary *_properties; // more data retained for caller + dispatch_queue_t _callbackQueue; + dispatch_group_t _callbackGroup; // read-only after creation + NSOperationQueue *_delegateQueue; // immutable after beginFetch + + id _authorizer; // immutable after beginFetch + + // The service object that created and monitors this fetcher, if any. + id _service; // immutable; set by the fetcher service upon creation + NSString *_serviceHost; + NSInteger _servicePriority; // immutable after beginFetch + BOOL _hasStoppedFetching; // counterpart to _initialBeginFetchDate + BOOL _userStoppedFetching; + + BOOL _isRetryEnabled; // user wants auto-retry + NSTimer *_retryTimer; + NSUInteger _retryCount; + NSTimeInterval _maxRetryInterval; // default 60 (download) or 600 (upload) seconds + NSTimeInterval _minRetryInterval; // random between 1 and 2 seconds + NSTimeInterval _retryFactor; // default interval multiplier is 2 + NSTimeInterval _lastRetryInterval; + NSDate *_initialBeginFetchDate; // date that beginFetch was first invoked; immutable after initial beginFetch + NSDate *_initialRequestDate; // date of first request to the target server (ignoring auth) + BOOL _hasAttemptedAuthRefresh; // accessed only in shouldRetryNowForStatus: + + NSString *_comment; // comment for log + NSString *_log; +#if !STRIP_GTM_FETCH_LOGGING + NSMutableData *_loggedStreamData; + NSURL *_redirectedFromURL; + NSString *_logRequestBody; + NSString *_logResponseBody; + BOOL _hasLoggedError; + BOOL _deferResponseBodyLogging; +#endif +} + +#if !GTMSESSION_UNIT_TESTING ++ (void)load { +#if GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH && TARGET_OS_IPHONE + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(reconnectFetchersForBackgroundSessionsOnAppLaunch:) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; +#elif GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH && TARGET_OS_OSX + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(reconnectFetchersForBackgroundSessionsOnAppLaunch:) + name:NSApplicationDidFinishLaunchingNotification + object:nil]; +#else + [self fetchersForBackgroundSessions]; +#endif +} + ++ (void)reconnectFetchersForBackgroundSessionsOnAppLaunch:(NSNotification *)notification { + // Give all other app-did-launch handlers a chance to complete before + // reconnecting the fetchers. Not doing this may lead to reconnecting + // before the app delegate has a chance to run. + dispatch_async(dispatch_get_main_queue(), ^{ + [self fetchersForBackgroundSessions]; + }); +} +#endif // !GTMSESSION_UNIT_TESTING + ++ (instancetype)fetcherWithRequest:(GTM_NULLABLE NSURLRequest *)request { + return [[self alloc] initWithRequest:request configuration:nil]; +} + ++ (instancetype)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + ++ (instancetype)fetcherWithURLString:(NSString *)requestURLString { + return [self fetcherWithURL:(NSURL *)[NSURL URLWithString:requestURLString]]; +} + ++ (instancetype)fetcherWithDownloadResumeData:(NSData *)resumeData { + GTMSessionFetcher *fetcher = [self fetcherWithRequest:nil]; + fetcher.comment = @"Resuming download"; + fetcher.downloadResumeData = resumeData; + return fetcher; +} + ++ (GTM_NULLABLE instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (!fetcher && [sessionIdentifier hasPrefix:kGTMSessionIdentifierPrefix]) { + fetcher = [self fetcherWithRequest:nil]; + [fetcher setSessionIdentifier:sessionIdentifier]; + [sessionIdentifierToFetcherMap setObject:fetcher forKey:sessionIdentifier]; + fetcher->_wasCreatedFromBackgroundSession = YES; + [fetcher setCommentWithFormat:@"Resuming %@", + fetcher && fetcher->_sessionIdentifierUUID ? fetcher->_sessionIdentifierUUID : @"?"]; + } + return fetcher; +} + ++ (NSMapTable *)sessionIdentifierToFetcherMap { + // TODO: What if a service is involved in creating the fetcher? Currently, when re-creating + // fetchers, if a service was involved, it is not re-created. Should the service maintain a map? + static NSMapTable *gSessionIdentifierToFetcherMap = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSessionIdentifierToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return gSessionIdentifierToFetcherMap; +} + +#if !GTM_ALLOW_INSECURE_REQUESTS ++ (BOOL)appAllowsInsecureRequests { + // If the main bundle Info.plist key NSAppTransportSecurity is present, and it specifies + // NSAllowsArbitraryLoads, then we need to explicitly enforce secure schemes. +#if GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY + static BOOL allowsInsecureRequests; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSBundle *mainBundle = [NSBundle mainBundle]; + NSDictionary *appTransportSecurity = + [mainBundle objectForInfoDictionaryKey:@"NSAppTransportSecurity"]; + allowsInsecureRequests = + [[appTransportSecurity objectForKey:@"NSAllowsArbitraryLoads"] boolValue]; + }); + return allowsInsecureRequests; +#else + // For builds targeting iOS 8 or 10.10 and earlier, we want to require fetcher + // security checks. + return YES; +#endif // GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY +} +#else // GTM_ALLOW_INSECURE_REQUESTS ++ (BOOL)appAllowsInsecureRequests { + return YES; +} +#endif // !GTM_ALLOW_INSECURE_REQUESTS + + +- (instancetype)init { + return [self initWithRequest:nil configuration:nil]; +} + +- (instancetype)initWithRequest:(NSURLRequest *)request { + return [self initWithRequest:request configuration:nil]; +} + +- (instancetype)initWithRequest:(GTM_NULLABLE NSURLRequest *)request + configuration:(GTM_NULLABLE NSURLSessionConfiguration *)configuration { + self = [super init]; + if (self) { +#if GTM_BACKGROUND_TASK_FETCHING + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; +#endif + _request = [request mutableCopy]; + _configuration = configuration; + + NSData *bodyData = request.HTTPBody; + if (bodyData) { + _bodyLength = (int64_t)bodyData.length; + } else { + _bodyLength = NSURLSessionTransferSizeUnknown; + } + + _callbackQueue = dispatch_get_main_queue(); + _callbackGroup = dispatch_group_create(); + _delegateQueue = [NSOperationQueue mainQueue]; + + _minRetryInterval = InitialMinRetryInterval(); + _maxRetryInterval = kUnsetMaxRetryInterval; + + _taskPriority = -1.0f; // Valid values if set are 0.0...1.0. + + _testBlockAccumulateDataChunkCount = 1; + +#if !STRIP_GTM_FETCH_LOGGING + // Encourage developers to set the comment property or use + // setCommentWithFormat: by providing a default string. + _comment = @"(No fetcher comment set)"; +#endif + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // disallow use of fetchers in a copy property + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (NSString *)description { + NSString *requestStr = self.request.URL.description; + if (requestStr.length == 0) { + if (self.downloadResumeData.length > 0) { + requestStr = @""; + } else if (_wasCreatedFromBackgroundSession) { + requestStr = @""; + } else { + requestStr = @""; + } + } + return [NSString stringWithFormat:@"%@ %p (%@)", [self class], self, requestStr]; +} + +- (void)dealloc { + GTMSESSION_ASSERT_DEBUG(!_isStopNotificationNeeded, + @"unbalanced fetcher notification for %@", _request.URL); + [self forgetSessionIdentifierForFetcherWithoutSyncCheck]; + + // Note: if a session task or a retry timer was pending, then this instance + // would be retained by those so it wouldn't be getting dealloc'd, + // hence we don't need to stopFetch here +} + +#pragma mark - + +// Begin fetching the URL (or begin a retry fetch). The delegate is retained +// for the duration of the fetch connection. + +- (void)beginFetchWithCompletionHandler:(GTM_NULLABLE GTMSessionFetcherCompletionHandler)handler { + GTMSessionCheckNotSynchronized(self); + + _completionHandler = [handler copy]; + + // The user may have called setDelegate: earlier if they want to use other + // delegate-style callbacks during the fetch; otherwise, the delegate is nil, + // which is fine. + [self beginFetchMayDelay:YES mayAuthorize:YES]; +} + +// Begin fetching the URL for a retry fetch. The delegate and completion handler +// are already provided, and do not need to be copied. +- (void)beginFetchForRetry { + GTMSessionCheckNotSynchronized(self); + + [self beginFetchMayDelay:YES mayAuthorize:YES]; +} + +- (GTMSessionFetcherCompletionHandler)completionHandlerWithTarget:(GTM_NULLABLE_TYPE id)target + didFinishSelector:(GTM_NULLABLE_TYPE SEL)finishedSelector { + GTMSessionFetcherAssertValidSelector(target, finishedSelector, @encode(GTMSessionFetcher *), + @encode(NSData *), @encode(NSError *), 0); + GTMSessionFetcherCompletionHandler completionHandler = ^(NSData *data, NSError *error) { + if (target && finishedSelector) { + id selfArg = self; // Placate ARC. + NSMethodSignature *sig = [target methodSignatureForSelector:finishedSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:(SEL)finishedSelector]; + [invocation setTarget:target]; + [invocation setArgument:&selfArg atIndex:2]; + [invocation setArgument:&data atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + }; + return completionHandler; +} + +- (void)beginFetchWithDelegate:(GTM_NULLABLE_TYPE id)target + didFinishSelector:(GTM_NULLABLE_TYPE SEL)finishedSelector { + GTMSessionCheckNotSynchronized(self); + + GTMSessionFetcherCompletionHandler handler = [self completionHandlerWithTarget:target + didFinishSelector:finishedSelector]; + [self beginFetchWithCompletionHandler:handler]; +} + +- (void)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize { + // This is the internal entry point for re-starting fetches. + GTMSessionCheckNotSynchronized(self); + + NSMutableURLRequest *fetchRequest = _request; // The request property is now externally immutable. + NSURL *fetchRequestURL = fetchRequest.URL; + NSString *priorSessionIdentifier = self.sessionIdentifier; + + // A utility block for creating error objects when we fail to start the fetch. + NSError *(^beginFailureError)(NSInteger) = ^(NSInteger code){ + NSString *urlString = fetchRequestURL.absoluteString; + NSDictionary *userInfo = @{ + NSURLErrorFailingURLStringErrorKey : (urlString ? urlString : @"(missing URL)") + }; + return [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:code + userInfo:userInfo]; + }; + + // Catch delegate queue maxConcurrentOperationCount values other than 1, particularly + // NSOperationQueueDefaultMaxConcurrentOperationCount (-1), to avoid the additional complexity + // of simultaneous or out-of-order delegate callbacks. + GTMSESSION_ASSERT_DEBUG(_delegateQueue.maxConcurrentOperationCount == 1, + @"delegate queue %@ should support one concurrent operation, not %ld", + _delegateQueue.name, + (long)_delegateQueue.maxConcurrentOperationCount); + + if (!_initialBeginFetchDate) { + // This ivar is set only here on the initial beginFetch so need not be synchronized. + _initialBeginFetchDate = [[NSDate alloc] init]; + } + + if (self.sessionTask != nil) { + // If cached fetcher returned through fetcherWithSessionIdentifier:, then it's + // already begun, but don't consider this a failure, since the user need not know this. + if (self.sessionIdentifier != nil) { + return; + } + GTMSESSION_ASSERT_DEBUG(NO, @"Fetch object %@ being reused; this should never happen", self); + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorDownloadFailed)]; + return; + } + + if (fetchRequestURL == nil && !_downloadResumeData && !priorSessionIdentifier) { + GTMSESSION_ASSERT_DEBUG(NO, @"Beginning a fetch requires a request with a URL"); + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorDownloadFailed)]; + return; + } + + // We'll respect the user's request for a background session (unless this is + // an upload fetcher, which does its initial request foreground.) + self.usingBackgroundSession = self.useBackgroundSession && [self canFetchWithBackgroundSession]; + + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSError *fileCheckError; + if (![bodyFileURL checkResourceIsReachableAndReturnError:&fileCheckError]) { + // This assert fires when the file being uploaded no longer exists once + // the fetcher is ready to start the upload. + GTMSESSION_ASSERT_DEBUG_OR_LOG(0, @"Body file is unreachable: %@\n %@", + bodyFileURL.path, fileCheckError); + [self failToBeginFetchWithError:fileCheckError]; + return; + } + } + + NSString *requestScheme = fetchRequestURL.scheme; + BOOL isDataRequest = [requestScheme isEqual:@"data"]; + if (isDataRequest) { + // NSURLSession does not support data URLs in background sessions. +#if DEBUG + if (priorSessionIdentifier || self.sessionIdentifier) { + GTMSESSION_LOG_DEBUG(@"Converting background to foreground session for %@", + fetchRequest); + } +#endif + // If priorSessionIdentifier is allowed to stay non-nil, a background session can + // still be created. + priorSessionIdentifier = nil; + [self setSessionIdentifierInternal:nil]; + self.usingBackgroundSession = NO; + } + +#if GTM_ALLOW_INSECURE_REQUESTS + BOOL shouldCheckSecurity = NO; +#else + BOOL shouldCheckSecurity = (fetchRequestURL != nil + && !isDataRequest + && [[self class] appAllowsInsecureRequests]); +#endif + + if (shouldCheckSecurity) { + // Allow https only for requests, unless overridden by the client. + // + // Non-https requests may too easily be snooped, so we disallow them by default. + // + // file: and data: schemes are usually safe if they are hardcoded in the client or provided + // by a trusted source, but since it's fairly rare to need them, it's safest to make clients + // explicitly whitelist them. + BOOL isSecure = + requestScheme != nil && [requestScheme caseInsensitiveCompare:@"https"] == NSOrderedSame; + if (!isSecure) { + BOOL allowRequest = NO; + NSString *host = fetchRequestURL.host; + + // Check schemes first. A file scheme request may be allowed here, or as a localhost request. + for (NSString *allowedScheme in _allowedInsecureSchemes) { + if (requestScheme != nil && + [requestScheme caseInsensitiveCompare:allowedScheme] == NSOrderedSame) { + allowRequest = YES; + break; + } + } + if (!allowRequest) { + // Check for localhost requests. Security checks only occur for non-https requests, so + // this check won't happen for an https request to localhost. + BOOL isLocalhostRequest = (host.length == 0 && [fetchRequestURL isFileURL]) || IsLocalhost(host); + if (isLocalhostRequest) { + if (self.allowLocalhostRequest) { + allowRequest = YES; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Fetch request for localhost but fetcher" + @" allowLocalhostRequest is not set: %@", fetchRequestURL); + } + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Insecure fetch request has a scheme (%@)" + @" not found in fetcher allowedInsecureSchemes (%@): %@", + requestScheme, _allowedInsecureSchemes ?: @" @[] ", fetchRequestURL); + } + } + + if (!allowRequest) { +#if !DEBUG + NSLog(@"Insecure fetch disallowed for %@", fetchRequestURL.description ?: @"nil request URL"); +#endif + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorInsecureRequest)]; + return; + } + } // !isSecure + } // (requestURL != nil) && !isDataRequest + + if (self.cookieStorage == nil) { + self.cookieStorage = [[self class] staticCookieStorage]; + } + + BOOL isRecreatingSession = (self.sessionIdentifier != nil) && (fetchRequest == nil); + + self.canShareSession = !isRecreatingSession && !self.usingBackgroundSession; + + if (!self.session && self.canShareSession) { + self.session = [_service sessionForFetcherCreation]; + // If _session is nil, then the service's session creation semaphore will block + // until this fetcher invokes fetcherDidCreateSession: below, so this *must* invoke + // that method, even if the session fails to be created. + } + + if (!self.session) { + // Create a session. + if (!_configuration) { + if (priorSessionIdentifier || self.usingBackgroundSession) { + NSString *sessionIdentifier = priorSessionIdentifier; + if (!sessionIdentifier) { + sessionIdentifier = [self createSessionIdentifierWithMetadata:nil]; + } + NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIdentifierToFetcherMap]; + [sessionIdentifierToFetcherMap setObject:self forKey:self.sessionIdentifier]; + + if (@available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.10, *)) { + _configuration = + [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionIdentifier]; + } else { +#if ((!TARGET_OS_IPHONE && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) \ + || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)) + // If building with support for iOS 7 or < macOS 10.10, allow using the older + // -backgroundSessionConfiguration: method, otherwise leave it out to avoid deprecated + // API warnings/errors. + _configuration = + [NSURLSessionConfiguration backgroundSessionConfiguration:sessionIdentifier]; +#endif + } + self.usingBackgroundSession = YES; + self.canShareSession = NO; + } else { + _configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + } +#if !GTM_ALLOW_INSECURE_REQUESTS +#if GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; +#elif GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION + if (@available(iOS 13, tvOS 13, watchOS 6, macOS 10.15, *)) { +#if TARGET_OS_IOS + // Early seeds of iOS 13 don't actually support the selector and several + // months later, those seeds are still in use, so validate if the selector + // is supported. + if ([_configuration respondsToSelector:@selector(setTLSMinimumSupportedProtocolVersion:)]) { + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; + } else { + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; + } +#else + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; +#endif // TARGET_OS_IOS + } else { + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; + } +#else + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; +#endif // GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION +#endif + } // !_configuration + _configuration.HTTPCookieStorage = self.cookieStorage; + + if (_configurationBlock) { + _configurationBlock(self, _configuration); + } + + id delegate = [_service sessionDelegate]; + if (!delegate || !self.canShareSession) { + delegate = self; + } + self.session = [NSURLSession sessionWithConfiguration:_configuration + delegate:delegate + delegateQueue:self.sessionDelegateQueue]; + GTMSESSION_ASSERT_DEBUG(self.session, @"Couldn't create session"); + + // Tell the service about the session created by this fetcher. This also signals the + // service's semaphore to allow other fetchers to request this session. + [_service fetcherDidCreateSession:self]; + + // If this assertion fires, the client probably tried to use a session identifier that was + // already used. The solution is to make the client use a unique identifier (or better yet let + // the session fetcher assign the identifier). + GTMSESSION_ASSERT_DEBUG(self.session.delegate == delegate, @"Couldn't assign delegate."); + + if (self.session) { + BOOL isUsingSharedDelegate = (delegate != self); + if (!isUsingSharedDelegate) { + _shouldInvalidateSession = YES; + } + } + } + + if (isRecreatingSession) { + _shouldInvalidateSession = YES; + + // Let's make sure there are tasks still running or if not that we get a callback from a + // completed one; otherwise, we assume the tasks failed. + // This is the observed behavior perhaps 25% of the time within the Simulator running 7.0.3 on + // exiting the app after starting an upload and relaunching the app if we manage to relaunch + // after the task has completed, but before the system relaunches us in the background. + [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, + NSArray *downloadTasks) { + if (dataTasks.count == 0 && uploadTasks.count == 0 && downloadTasks.count == 0) { + double const kDelayInSeconds = 1.0; // We should get progress indication or completion soon + dispatch_time_t checkForFeedbackDelay = + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayInSeconds * NSEC_PER_SEC)); + dispatch_after(checkForFeedbackDelay, dispatch_get_main_queue(), ^{ + if (!self.sessionTask && !fetchRequest) { + // If our task and/or request haven't been restored, then we assume task feedback lost. + [self removePersistedBackgroundSessionFromDefaults]; + NSError *sessionError = + [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorBackgroundFetchFailed + userInfo:nil]; + [self failToBeginFetchWithError:sessionError]; + } + }); + } + }]; + return; + } + + self.downloadedData = nil; + self.downloadedLength = 0; + + if (_servicePriority == NSIntegerMin) { + mayDelay = NO; + } + if (mayDelay && _service) { + BOOL shouldFetchNow = [_service fetcherShouldBeginFetching:self]; + if (!shouldFetchNow) { + // The fetch is deferred, but will happen later. + // + // If this session is held by the fetcher service, clear the session now so that we don't + // assume it's still valid after the fetcher is restarted. + if (self.canShareSession) { + self.session = nil; + } + return; + } + } + + NSString *effectiveHTTPMethod = [fetchRequest valueForHTTPHeaderField:@"X-HTTP-Method-Override"]; + if (effectiveHTTPMethod == nil) { + effectiveHTTPMethod = fetchRequest.HTTPMethod; + } + BOOL isEffectiveHTTPGet = (effectiveHTTPMethod == nil + || [effectiveHTTPMethod isEqual:@"GET"]); + + BOOL needsUploadTask = (self.useUploadTask || self.bodyFileURL || self.bodyStreamProvider); + if (_bodyData || self.bodyStreamProvider || fetchRequest.HTTPBodyStream) { + if (isEffectiveHTTPGet) { + fetchRequest.HTTPMethod = @"POST"; + isEffectiveHTTPGet = NO; + } + + if (_bodyData) { + if (!needsUploadTask) { + fetchRequest.HTTPBody = _bodyData; + } +#if !STRIP_GTM_FETCH_LOGGING + } else if (fetchRequest.HTTPBodyStream) { + if ([self respondsToSelector:@selector(loggedInputStreamForInputStream:)]) { + fetchRequest.HTTPBodyStream = + [self performSelector:@selector(loggedInputStreamForInputStream:) + withObject:fetchRequest.HTTPBodyStream]; + } +#endif + } + } + + // We authorize after setting up the http method and body in the request + // because OAuth 1 may need to sign the request body + if (mayAuthorize && _authorizer && !isDataRequest) { + BOOL isAuthorized = [_authorizer isAuthorizedRequest:fetchRequest]; + if (!isAuthorized) { + // Authorization needed. + // + // If this session is held by the fetcher service, clear the session now so that we don't + // assume it's still valid after authorization completes. + if (self.canShareSession) { + self.session = nil; + } + + // Authorizing the request will recursively call this beginFetch:mayDelay: + // or failToBeginFetchWithError:. + [self authorizeRequest]; + return; + } + } + + // set the default upload or download retry interval, if necessary + if ([self isRetryEnabled] && self.maxRetryInterval <= 0) { + if (isEffectiveHTTPGet || [effectiveHTTPMethod isEqual:@"HEAD"]) { + [self setMaxRetryInterval:kDefaultMaxDownloadRetryInterval]; + } else { + [self setMaxRetryInterval:kDefaultMaxUploadRetryInterval]; + } + } + + // finally, start the connection + NSURLSessionTask *newSessionTask; + BOOL needsDataAccumulator = NO; + if (_downloadResumeData) { + newSessionTask = [_session downloadTaskWithResumeData:_downloadResumeData]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed downloadTaskWithResumeData for %@, resume data %lu bytes", + _session, (unsigned long)_downloadResumeData.length); + } else if (_destinationFileURL && !isDataRequest) { + newSessionTask = [_session downloadTaskWithRequest:fetchRequest]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, @"Failed downloadTaskWithRequest for %@, %@", + _session, fetchRequest); + } else if (needsUploadTask) { + if (bodyFileURL) { + newSessionTask = [_session uploadTaskWithRequest:fetchRequest + fromFile:bodyFileURL]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithRequest for %@, %@, file %@", + _session, fetchRequest, bodyFileURL.path); + } else if (self.bodyStreamProvider) { + newSessionTask = [_session uploadTaskWithStreamedRequest:fetchRequest]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithStreamedRequest for %@, %@", + _session, fetchRequest); + } else { + GTMSESSION_ASSERT_DEBUG_OR_LOG(_bodyData != nil, + @"Upload task needs body data, %@", fetchRequest); + newSessionTask = [_session uploadTaskWithRequest:fetchRequest + fromData:(NSData * GTM_NONNULL_TYPE)_bodyData]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithRequest for %@, %@, body data %lu bytes", + _session, fetchRequest, (unsigned long)_bodyData.length); + } + needsDataAccumulator = YES; + } else { + newSessionTask = [_session dataTaskWithRequest:fetchRequest]; + needsDataAccumulator = YES; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, @"Failed dataTaskWithRequest for %@, %@", + _session, fetchRequest); + } + self.sessionTask = newSessionTask; + + if (!newSessionTask) { + // We shouldn't get here; if we're here, an earlier assertion should have fired to explain + // which session task creation failed. + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorTaskCreationFailed)]; + return; + } + + if (needsDataAccumulator && _accumulateDataBlock == nil) { + self.downloadedData = [NSMutableData data]; + } + if (_taskDescription) { + newSessionTask.taskDescription = _taskDescription; + } + if (_taskPriority >= 0) { + if (@available(iOS 8.0, macOS 10.10, *)) { + newSessionTask.priority = _taskPriority; + } + } + +#if GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSESSION_ASSERT_DEBUG(_testBlock == nil && gGlobalTestBlock == nil, @"test blocks disabled"); + _testBlock = nil; +#else + if (!_testBlock) { + if (gGlobalTestBlock) { + // Note that the test block may pass nil for all of its response parameters, + // indicating that the fetch should actually proceed. This is useful when the + // global test block has been set, and the app is only testing a specific + // fetcher. The block simulation code will then resume the task. + _testBlock = gGlobalTestBlock; + } + } + _isUsingTestBlock = (_testBlock != nil); +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK + +#if GTM_BACKGROUND_TASK_FETCHING + id app = [[self class] fetcherUIApplication]; + // Background tasks seem to interfere with out-of-process uploads and downloads. + if (app && !self.skipBackgroundTask && !self.usingBackgroundSession) { + // Tell UIApplication that we want to continue even when the app is in the + // background. +#if DEBUG + NSString *bgTaskName = [NSString stringWithFormat:@"%@-%@", + [self class], fetchRequest.URL.host]; +#else + NSString *bgTaskName = @"GTMSessionFetcher"; +#endif + __block UIBackgroundTaskIdentifier bgTaskID = [app beginBackgroundTaskWithName:bgTaskName + expirationHandler:^{ + // Background task expiration callback - this block is always invoked by + // UIApplication on the main thread. + if (bgTaskID != UIBackgroundTaskInvalid) { + @synchronized(self) { + if (bgTaskID == self.backgroundTaskIdentifier) { + self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + } + [app endBackgroundTask:bgTaskID]; + } + }]; + @synchronized(self) { + self.backgroundTaskIdentifier = bgTaskID; + } + } +#endif + + if (!_initialRequestDate) { + _initialRequestDate = [[NSDate alloc] init]; + } + + // We don't expect to reach here even on retry or auth until a stop notification has been sent + // for the previous task, but we should ensure that we don't unbalance that. + GTMSESSION_ASSERT_DEBUG(!_isStopNotificationNeeded, @"Start notification without a prior stop"); + [self sendStopNotificationIfNeeded]; + + [self addPersistedBackgroundSessionToDefaults]; + + [self setStopNotificationNeeded:YES]; + + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherStartedNotification + userInfo:nil + requireAsync:NO]; + + // The service needs to know our task if it is serving as NSURLSession delegate. + [_service fetcherDidBeginFetching:self]; + + if (_testBlock) { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + [self simulateFetchForTestBlock]; +#endif + } else { + // We resume the session task after posting the notification since the + // delegate callbacks may happen immediately if the fetch is started off + // the main thread or the session delegate queue is on a background thread, + // and we don't want to post a start notification after a premature finish + // of the session task. + [newSessionTask resume]; + } +} + +NSData * GTM_NULLABLE_TYPE GTMDataFromInputStream(NSInputStream *inputStream, NSError **outError) { + NSMutableData *data = [NSMutableData data]; + + [inputStream open]; + NSInteger numberOfBytesRead = 0; + while ([inputStream hasBytesAvailable]) { + uint8_t buffer[512]; + numberOfBytesRead = [inputStream read:buffer maxLength:sizeof(buffer)]; + if (numberOfBytesRead > 0) { + [data appendBytes:buffer length:(NSUInteger)numberOfBytesRead]; + } else { + break; + } + } + [inputStream close]; + NSError *streamError = inputStream.streamError; + + if (streamError) { + data = nil; + } + if (outError) { + *outError = streamError; + } + return data; +} + +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + +- (void)simulateFetchForTestBlock { + // This is invoked on the same thread as the beginFetch method was. + // + // Callbacks will all occur on the callback queue. + _testBlock(self, ^(NSURLResponse *response, NSData *responseData, NSError *error) { + // Callback from test block. + if (response == nil && responseData == nil && error == nil) { + // Assume the fetcher should execute rather than be tested. + self->_testBlock = nil; + self->_isUsingTestBlock = NO; + [self->_sessionTask resume]; + return; + } + + GTMSessionFetcherBodyStreamProvider bodyStreamProvider = self.bodyStreamProvider; + if (bodyStreamProvider) { + bodyStreamProvider(^(NSInputStream *bodyStream){ + // Read from the input stream into an NSData buffer. We'll drain the stream + // explicitly on a background queue. + [self invokeOnCallbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) + afterUserStopped:NO + block:^{ + NSError *streamError; + NSData *streamedData = GTMDataFromInputStream(bodyStream, &streamError); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Continue callbacks on the main thread, since serial behavior + // is more reliable for tests. + [self simulateDataCallbacksForTestBlockWithBodyData:streamedData + response:response + responseData:responseData + error:(error ?: streamError)]; + }); + }]; + }); + } else { + // No input stream; use the supplied data or file URL. + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSError *readError; + self->_bodyData = [NSData dataWithContentsOfURL:bodyFileURL + options:NSDataReadingMappedIfSafe + error:&readError]; + error = readError; + } + + // No stream provider. + + // In real fetches, nothing happens until the run loop spins, so apps have leeway to + // set callbacks after they call beginFetch. We'll mirror that fetcher behavior by + // delaying callbacks here at least to the next spin of the run loop. That keeps + // immediate, synchronous setting of callback blocks after beginFetch working in tests. + dispatch_async(dispatch_get_main_queue(), ^{ + [self simulateDataCallbacksForTestBlockWithBodyData:self->_bodyData + response:response + responseData:responseData + error:error]; + }); + } + }); +} + +- (void)simulateByteTransferReportWithDataLength:(int64_t)totalDataLength + block:(GTMSessionFetcherSendProgressBlock)block { + // This utility method simulates transfer progress with up to three callbacks. + // It is used to call back to any of the progress blocks. + int64_t sendReportSize = totalDataLength / 3 + 1; + int64_t totalSent = 0; + while (totalSent < totalDataLength) { + int64_t bytesRemaining = totalDataLength - totalSent; + sendReportSize = MIN(sendReportSize, bytesRemaining); + totalSent += sendReportSize; + [self invokeOnCallbackQueueUnlessStopped:^{ + block(sendReportSize, totalSent, totalDataLength); + }]; + } +} + +- (void)simulateDataCallbacksForTestBlockWithBodyData:(NSData * GTM_NULLABLE_TYPE)bodyData + response:(NSURLResponse *)response + responseData:(NSData *)suppliedData + error:(NSError *)suppliedError { + __block NSData *responseData = suppliedData; + __block NSError *responseError = suppliedError; + + // This method does the test simulation of callbacks once the upload + // and download data are known. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Get copies of ivars we'll access in async invocations. This simulation assumes + // they won't change during fetcher execution. + NSURL *destinationFileURL = _destinationFileURL; + GTMSessionFetcherWillRedirectBlock willRedirectBlock = _willRedirectBlock; + GTMSessionFetcherDidReceiveResponseBlock didReceiveResponseBlock = _didReceiveResponseBlock; + GTMSessionFetcherSendProgressBlock sendProgressBlock = _sendProgressBlock; + GTMSessionFetcherDownloadProgressBlock downloadProgressBlock = _downloadProgressBlock; + GTMSessionFetcherAccumulateDataBlock accumulateDataBlock = _accumulateDataBlock; + GTMSessionFetcherReceivedProgressBlock receivedProgressBlock = _receivedProgressBlock; + GTMSessionFetcherWillCacheURLResponseBlock willCacheURLResponseBlock = + _willCacheURLResponseBlock; + GTMSessionFetcherChallengeBlock challengeBlock = _challengeBlock; + + // Simulate receipt of redirection. + if (willRedirectBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + willRedirectBlock((NSHTTPURLResponse *)response, self->_request, + ^(NSURLRequest *redirectRequest) { + // For simulation, we'll assume the app will just continue. + }); + }]; + } + + // If the fetcher has a challenge block, simulate a challenge. + // + // It might be nice to eventually let the user determine which testBlock + // fetches get challenged rather than always executing the supplied + // challenge block. + if (challengeBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + NSURL *requestURL = self->_request.URL; + NSString *host = requestURL.host; + NSURLProtectionSpace *pspace = + [[NSURLProtectionSpace alloc] initWithHost:host + port:requestURL.port.integerValue + protocol:requestURL.scheme + realm:nil + authenticationMethod:NSURLAuthenticationMethodHTTPBasic]; + id unusedSender = + (id)[NSNull null]; + NSURLAuthenticationChallenge *challenge = + [[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:pspace + proposedCredential:nil + previousFailureCount:0 + failureResponse:nil + error:nil + sender:unusedSender]; + challengeBlock(self, challenge, ^(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential){ + // We could change the responseData and responseError based on the disposition, + // but it's easier for apps to just supply the expected data and error + // directly to the test block. So this simulation ignores the disposition. + }); + }]; + } + + // Simulate receipt of an initial response. + if (response && didReceiveResponseBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + didReceiveResponseBlock(response, ^(NSURLSessionResponseDisposition desiredDisposition) { + // For simulation, we'll assume the disposition is to continue. + }); + }]; + } + + // Simulate reporting send progress. + if (sendProgressBlock) { + [self simulateByteTransferReportWithDataLength:(int64_t)bodyData.length + block:^(int64_t bytesSent, + int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + // This is invoked on the callback queue unless stopped. + sendProgressBlock(bytesSent, totalBytesSent, totalBytesExpectedToSend); + }]; + } + + if (destinationFileURL) { + // Simulate download to file progress. + if (downloadProgressBlock) { + [self simulateByteTransferReportWithDataLength:(int64_t)responseData.length + block:^(int64_t bytesDownloaded, + int64_t totalBytesDownloaded, + int64_t totalBytesExpectedToDownload) { + // This is invoked on the callback queue unless stopped. + downloadProgressBlock(bytesDownloaded, totalBytesDownloaded, + totalBytesExpectedToDownload); + }]; + } + + NSError *writeError; + [responseData writeToURL:destinationFileURL + options:NSDataWritingAtomic + error:&writeError]; + if (writeError) { + // Tell the test code that writing failed. + responseError = writeError; + } + } else { + // Simulate download to NSData progress. + if ((accumulateDataBlock || receivedProgressBlock) && responseData) { + [self simulateByteTransferWithData:responseData + block:^(NSData *data, + int64_t bytesReceived, + int64_t totalBytesReceived, + int64_t totalBytesExpectedToReceive) { + // This is invoked on the callback queue unless stopped. + if (accumulateDataBlock) { + accumulateDataBlock(data); + } + + if (receivedProgressBlock) { + receivedProgressBlock(bytesReceived, totalBytesReceived); + } + }]; + } + + if (!accumulateDataBlock) { + _downloadedData = [responseData mutableCopy]; + } + + if (willCacheURLResponseBlock) { + // Simulate letting the client inspect and alter the cached response. + NSData *cachedData = responseData ?: [[NSData alloc] init]; // Always have non-nil data. + NSCachedURLResponse *cachedResponse = + [[NSCachedURLResponse alloc] initWithResponse:response + data:cachedData]; + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + willCacheURLResponseBlock(cachedResponse, ^(NSCachedURLResponse *responseToCache){ + // The app may provide an alternative response, or nil to defeat caching. + }); + }]; + } + } + _response = response; + } // @synchronized(self) + + NSOperationQueue *queue = self.sessionDelegateQueue; + [queue addOperationWithBlock:^{ + // Rather than invoke failToBeginFetchWithError: we want to simulate completion of + // a connection that started and ended, so we'll call down to finishWithError: + NSInteger status = responseError ? responseError.code : 200; + if (status >= 200 && status <= 399) { + [self finishWithError:nil shouldRetry:NO]; + } else { + [self shouldRetryNowForStatus:status + error:responseError + forceAssumeRetry:NO + response:^(BOOL shouldRetry) { + [self finishWithError:responseError shouldRetry:shouldRetry]; + }]; + } + }]; +} + +- (void)simulateByteTransferWithData:(NSData *)responseData + block:(GTMSessionFetcherSimulateByteTransferBlock)transferBlock { + // This utility method simulates transfering data to the client. It divides the data into at most + // "chunkCount" chunks and then passes each chunk along with a progress update to transferBlock. + // This function can be used with accumulateDataBlock or receivedProgressBlock. + + NSUInteger chunkCount = MAX(self.testBlockAccumulateDataChunkCount, (NSUInteger) 1); + NSUInteger totalDataLength = responseData.length; + NSUInteger sendDataSize = totalDataLength / chunkCount + 1; + NSUInteger totalSent = 0; + while (totalSent < totalDataLength) { + NSUInteger bytesRemaining = totalDataLength - totalSent; + sendDataSize = MIN(sendDataSize, bytesRemaining); + NSData *chunkData = [responseData subdataWithRange:NSMakeRange(totalSent, sendDataSize)]; + totalSent += sendDataSize; + [self invokeOnCallbackQueueUnlessStopped:^{ + transferBlock(chunkData, + (int64_t)sendDataSize, + (int64_t)totalSent, + (int64_t)totalDataLength); + }]; + } +} + +#endif // !GTM_DISABLE_FETCHER_TEST_BLOCK + +- (void)setSessionTask:(NSURLSessionTask *)sessionTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionTask != sessionTask) { + _sessionTask = sessionTask; + if (_sessionTask) { + // Request could be nil on restoring this fetcher from a background session. + if (!_request) { + _request = [_sessionTask.originalRequest mutableCopy]; + } + } + } + } // @synchronized(self) +} + +- (NSURLSessionTask * GTM_NULLABLE_TYPE)sessionTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionTask; + } // @synchronized(self) +} + ++ (NSUserDefaults *)fetcherUserDefaults { + static NSUserDefaults *gFetcherUserDefaults = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class fetcherUserDefaultsClass = NSClassFromString(@"GTMSessionFetcherUserDefaultsFactory"); + if (fetcherUserDefaultsClass) { + gFetcherUserDefaults = [fetcherUserDefaultsClass fetcherUserDefaults]; + } else { + gFetcherUserDefaults = [NSUserDefaults standardUserDefaults]; + } + }); + return gFetcherUserDefaults; +} + +- (void)addPersistedBackgroundSessionToDefaults { + NSString *sessionIdentifier = self.sessionIdentifier; + if (!sessionIdentifier) { + return; + } + NSArray *oldBackgroundSessions = [[self class] activePersistedBackgroundSessions]; + if ([oldBackgroundSessions containsObject:_sessionIdentifier]) { + return; + } + NSMutableArray *newBackgroundSessions = + [NSMutableArray arrayWithArray:oldBackgroundSessions]; + [newBackgroundSessions addObject:sessionIdentifier]; + GTM_LOG_BACKGROUND_SESSION(@"Add to background sessions: %@", newBackgroundSessions); + + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + [userDefaults setObject:newBackgroundSessions + forKey:kGTMSessionFetcherPersistedDestinationKey]; + [userDefaults synchronize]; +} + +- (void)removePersistedBackgroundSessionFromDefaults { + NSString *sessionIdentifier = self.sessionIdentifier; + if (!sessionIdentifier) return; + + NSArray *oldBackgroundSessions = [[self class] activePersistedBackgroundSessions]; + if (!oldBackgroundSessions) { + return; + } + NSMutableArray *newBackgroundSessions = + [NSMutableArray arrayWithArray:oldBackgroundSessions]; + NSUInteger sessionIndex = [newBackgroundSessions indexOfObject:sessionIdentifier]; + if (sessionIndex == NSNotFound) { + return; + } + [newBackgroundSessions removeObjectAtIndex:sessionIndex]; + GTM_LOG_BACKGROUND_SESSION(@"Remove from background sessions: %@", newBackgroundSessions); + + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + if (newBackgroundSessions.count == 0) { + [userDefaults removeObjectForKey:kGTMSessionFetcherPersistedDestinationKey]; + } else { + [userDefaults setObject:newBackgroundSessions + forKey:kGTMSessionFetcherPersistedDestinationKey]; + } + [userDefaults synchronize]; +} + ++ (GTM_NULLABLE NSArray *)activePersistedBackgroundSessions { + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + NSArray *oldBackgroundSessions = + [userDefaults arrayForKey:kGTMSessionFetcherPersistedDestinationKey]; + if (oldBackgroundSessions.count == 0) { + return nil; + } + NSMutableArray *activeBackgroundSessions = nil; + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + for (NSString *sessionIdentifier in oldBackgroundSessions) { + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (fetcher) { + if (!activeBackgroundSessions) { + activeBackgroundSessions = [[NSMutableArray alloc] init]; + } + [activeBackgroundSessions addObject:sessionIdentifier]; + } + } + return activeBackgroundSessions; +} + ++ (NSArray *)fetchersForBackgroundSessions { + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + NSArray *backgroundSessions = + [userDefaults arrayForKey:kGTMSessionFetcherPersistedDestinationKey]; + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + NSMutableArray *fetchers = [NSMutableArray array]; + for (NSString *sessionIdentifier in backgroundSessions) { + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (!fetcher) { + fetcher = [self fetcherWithSessionIdentifier:sessionIdentifier]; + GTMSESSION_ASSERT_DEBUG(fetcher != nil, + @"Unexpected invalid session identifier: %@", sessionIdentifier); + [fetcher beginFetchWithCompletionHandler:nil]; + } + GTM_LOG_BACKGROUND_SESSION(@"%@ restoring session %@ by creating fetcher %@ %p", + [self class], sessionIdentifier, fetcher, fetcher); + if (fetcher != nil) { + [fetchers addObject:fetcher]; + } + } + return fetchers; +} + +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH ++ (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(GTMSessionFetcherSystemCompletionHandler)completionHandler { + GTMSessionFetcher *fetcher = [self fetcherWithSessionIdentifier:identifier]; + if (fetcher != nil) { + fetcher.systemCompletionHandler = completionHandler; + } else { + GTM_LOG_BACKGROUND_SESSION(@"%@ did not create background session identifier: %@", + [self class], identifier); + } +} +#endif + +- (NSString * GTM_NULLABLE_TYPE)sessionIdentifier { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionIdentifier; + } // @synchronized(self) +} + +- (void)setSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(!_session, @"Unable to set session identifier after session created"); + _sessionIdentifier = [sessionIdentifier copy]; + _usingBackgroundSession = YES; + _canShareSession = NO; + [self restoreDefaultStateForSessionIdentifierMetadata]; + } // @synchronized(self) +} + +- (void)setSessionIdentifierInternal:(GTM_NULLABLE NSString *)sessionIdentifier { + // This internal method only does a synchronized set of the session identifier. + // It does not have side effects on the background session, shared session, or + // session identifier metadata. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _sessionIdentifier = [sessionIdentifier copy]; + } // @synchronized(self) +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionUserInfo { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionUserInfo == nil) { + // We'll return the metadata dictionary with internal keys removed. This avoids the user + // re-using the userInfo dictionary later and accidentally including the internal keys. + NSMutableDictionary *metadata = [[self sessionIdentifierMetadataUnsynchronized] mutableCopy]; + NSSet *keysToRemove = [metadata keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) { + return [key hasPrefix:@"_"]; + }]; + [metadata removeObjectsForKeys:[keysToRemove allObjects]]; + if (metadata.count > 0) { + _sessionUserInfo = metadata; + } + } + return _sessionUserInfo; + } // @synchronized(self) +} + +- (void)setSessionUserInfo:(NSDictionary * GTM_NULLABLE_TYPE)dictionary { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(_sessionIdentifier == nil, @"Too late to assign userInfo"); + _sessionUserInfo = dictionary; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSDictionary *)sessionIdentifierDefaultMetadata { + GTMSessionCheckSynchronized(self); + + NSMutableDictionary *defaultUserInfo = [[NSMutableDictionary alloc] init]; + if (_destinationFileURL) { + defaultUserInfo[kGTMSessionIdentifierDestinationFileURLMetadataKey] = + [_destinationFileURL absoluteString]; + } + if (_bodyFileURL) { + defaultUserInfo[kGTMSessionIdentifierBodyFileURLMetadataKey] = [_bodyFileURL absoluteString]; + } + return (defaultUserInfo.count > 0) ? defaultUserInfo : nil; +} + +- (void)restoreDefaultStateForSessionIdentifierMetadata { + GTMSessionCheckSynchronized(self); + + NSDictionary *metadata = [self sessionIdentifierMetadataUnsynchronized]; + NSString *destinationFileURLString = metadata[kGTMSessionIdentifierDestinationFileURLMetadataKey]; + if (destinationFileURLString) { + _destinationFileURL = [NSURL URLWithString:destinationFileURLString]; + GTM_LOG_BACKGROUND_SESSION(@"Restoring destination file URL: %@", _destinationFileURL); + } + NSString *bodyFileURLString = metadata[kGTMSessionIdentifierBodyFileURLMetadataKey]; + if (bodyFileURLString) { + _bodyFileURL = [NSURL URLWithString:bodyFileURLString]; + GTM_LOG_BACKGROUND_SESSION(@"Restoring body file URL: %@", _bodyFileURL); + } +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionIdentifierMetadata { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [self sessionIdentifierMetadataUnsynchronized]; + } +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionIdentifierMetadataUnsynchronized { + GTMSessionCheckSynchronized(self); + + // Session Identifier format: "com.google.__ + if (!_sessionIdentifier) { + return nil; + } + NSScanner *metadataScanner = [NSScanner scannerWithString:_sessionIdentifier]; + [metadataScanner setCharactersToBeSkipped:nil]; + NSString *metadataString; + NSString *uuid; + if ([metadataScanner scanUpToString:@"_" intoString:NULL] && + [metadataScanner scanString:@"_" intoString:NULL] && + [metadataScanner scanUpToString:@"_" intoString:&uuid] && + [metadataScanner scanString:@"_" intoString:NULL] && + [metadataScanner scanUpToString:@"\n" intoString:&metadataString]) { + _sessionIdentifierUUID = uuid; + NSData *metadataData = [metadataString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + NSDictionary *metadataDict = + [NSJSONSerialization JSONObjectWithData:metadataData + options:0 + error:&error]; + GTM_LOG_BACKGROUND_SESSION(@"User Info from session identifier: %@ %@", + metadataDict, error ? error : @""); + return metadataDict; + } + return nil; +} + +- (NSString *)createSessionIdentifierWithMetadata:(NSDictionary * GTM_NULLABLE_TYPE)metadataToInclude { + NSString *result; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Session Identifier format: "com.google.__ + GTMSESSION_ASSERT_DEBUG(!_sessionIdentifier, @"Session identifier already created"); + _sessionIdentifierUUID = [[NSUUID UUID] UUIDString]; + _sessionIdentifier = + [NSString stringWithFormat:@"%@_%@", kGTMSessionIdentifierPrefix, _sessionIdentifierUUID]; + // Start with user-supplied keys so they cannot accidentally override the fetcher's keys. + NSMutableDictionary *metadataDict = + [NSMutableDictionary dictionaryWithDictionary:(NSDictionary * GTM_NONNULL_TYPE)_sessionUserInfo]; + + if (metadataToInclude) { + [metadataDict addEntriesFromDictionary:(NSDictionary *)metadataToInclude]; + } + NSDictionary *defaultMetadataDict = [self sessionIdentifierDefaultMetadata]; + if (defaultMetadataDict) { + [metadataDict addEntriesFromDictionary:defaultMetadataDict]; + } + if (metadataDict.count > 0) { + NSData *metadataData = [NSJSONSerialization dataWithJSONObject:metadataDict + options:0 + error:NULL]; + GTMSESSION_ASSERT_DEBUG(metadataData != nil, + @"Session identifier user info failed to convert to JSON"); + if (metadataData.length > 0) { + NSString *metadataString = [[NSString alloc] initWithData:metadataData + encoding:NSUTF8StringEncoding]; + _sessionIdentifier = + [_sessionIdentifier stringByAppendingFormat:@"_%@", metadataString]; + } + } + _didCreateSessionIdentifier = YES; + result = _sessionIdentifier; + } // @synchronized(self) + return result; +} + +- (void)failToBeginFetchWithError:(NSError *)error { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _hasStoppedFetching = YES; + } + + if (error == nil) { + error = [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorDownloadFailed + userInfo:nil]; + } + + [self invokeFetchCallbacksOnCallbackQueueWithData:nil + error:error]; + [self releaseCallbacks]; + + [_service fetcherDidStop:self]; + + self.authorizer = nil; +} + ++ (GTMSessionCookieStorage *)staticCookieStorage { + static GTMSessionCookieStorage *gCookieStorage = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gCookieStorage = [[GTMSessionCookieStorage alloc] init]; + }); + return gCookieStorage; +} + +#if GTM_BACKGROUND_TASK_FETCHING + +- (void)endBackgroundTask { + // Whenever the connection stops or background execution expires, + // we need to tell UIApplication we're done. + UIBackgroundTaskIdentifier bgTaskID; + @synchronized(self) { + bgTaskID = self.backgroundTaskIdentifier; + if (bgTaskID != UIBackgroundTaskInvalid) { + self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + } + + if (bgTaskID != UIBackgroundTaskInvalid) { + id app = [[self class] fetcherUIApplication]; + [app endBackgroundTask:bgTaskID]; + } +} + +#endif // GTM_BACKGROUND_TASK_FETCHING + +- (void)authorizeRequest { + GTMSessionCheckNotSynchronized(self); + + id authorizer = self.authorizer; + SEL asyncAuthSel = @selector(authorizeRequest:delegate:didFinishSelector:); + if ([authorizer respondsToSelector:asyncAuthSel]) { + SEL callbackSel = @selector(authorizer:request:finishedWithError:); + NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; + [authorizer authorizeRequest:mutableRequest + delegate:self + didFinishSelector:callbackSel]; + } else { + GTMSESSION_ASSERT_DEBUG(authorizer == nil, @"invalid authorizer for fetch"); + + // No authorizing possible, and authorizing happens only after any delay; + // just begin fetching + [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + +- (void)authorizer:(id)auth + request:(NSMutableURLRequest *)authorizedRequest + finishedWithError:(NSError *)error { + GTMSessionCheckNotSynchronized(self); + + if (error != nil) { + // We can't fetch without authorization + [self failToBeginFetchWithError:error]; + } else { + @synchronized(self) { + _request = authorizedRequest; + } + [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + + +- (BOOL)canFetchWithBackgroundSession { + // Subclasses may override. + return YES; +} + +// Returns YES if the fetcher has been started and has not yet stopped. +// +// Fetching includes waiting for authorization or for retry, waiting to be allowed by the +// service object to start the request, and actually fetching the request. +- (BOOL)isFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [self isFetchingUnsynchronized]; + } +} + +- (BOOL)isFetchingUnsynchronized { + GTMSessionCheckSynchronized(self); + + BOOL hasBegun = (_initialBeginFetchDate != nil); + return hasBegun && !_hasStoppedFetching; +} + +- (NSURLResponse * GTM_NULLABLE_TYPE)response { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + return response; + } // @synchronized(self) +} + +- (NSURLResponse * GTM_NULLABLE_TYPE)responseUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = _sessionTask.response; + if (!response) response = _response; + return response; +} + +- (NSInteger)statusCode { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSInteger statusCode = [self statusCodeUnsynchronized]; + return statusCode; + } // @synchronized(self) +} + +- (NSInteger)statusCodeUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + NSInteger statusCode; + + if ([response respondsToSelector:@selector(statusCode)]) { + statusCode = [(NSHTTPURLResponse *)response statusCode]; + } else { + // Default to zero, in hopes of hinting "Unknown" (we can't be + // sure that things are OK enough to use 200). + statusCode = 0; + } + return statusCode; +} + +- (NSDictionary * GTM_NULLABLE_TYPE)responseHeaders { + GTMSessionCheckNotSynchronized(self); + + NSURLResponse *response = self.response; + if ([response respondsToSelector:@selector(allHeaderFields)]) { + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + return headers; + } + return nil; +} + +- (NSDictionary * GTM_NULLABLE_TYPE)responseHeadersUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + if ([response respondsToSelector:@selector(allHeaderFields)]) { + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + return headers; + } + return nil; +} + +- (void)releaseCallbacks { + // Avoid releasing blocks in the sync section since objects dealloc'd by + // the blocks being released may call back into the fetcher or fetcher + // service. + dispatch_queue_t NS_VALID_UNTIL_END_OF_SCOPE holdCallbackQueue; + GTMSessionFetcherCompletionHandler NS_VALID_UNTIL_END_OF_SCOPE holdCompletionHandler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + holdCallbackQueue = _callbackQueue; + holdCompletionHandler = _completionHandler; + + _callbackQueue = nil; + _completionHandler = nil; // Setter overridden in upload. Setter assumed to be used externally. + } + + // Set local callback pointers to nil here rather than let them release at the end of the scope + // to make any problems due to the blocks being released be a bit more obvious in a stack trace. + holdCallbackQueue = nil; + holdCompletionHandler = nil; + + self.configurationBlock = nil; + self.didReceiveResponseBlock = nil; + self.challengeBlock = nil; + self.willRedirectBlock = nil; + self.sendProgressBlock = nil; + self.receivedProgressBlock = nil; + self.downloadProgressBlock = nil; + self.accumulateDataBlock = nil; + self.willCacheURLResponseBlock = nil; + self.retryBlock = nil; + self.testBlock = nil; + self.resumeDataBlock = nil; + if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) { + self.metricsCollectionBlock = nil; + } +} + +- (void)forgetSessionIdentifierForFetcher { + GTMSessionCheckSynchronized(self); + [self forgetSessionIdentifierForFetcherWithoutSyncCheck]; +} + +- (void)forgetSessionIdentifierForFetcherWithoutSyncCheck { + // This should be called inside a @synchronized block (except during dealloc.) + if (_sessionIdentifier) { + NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIdentifierToFetcherMap]; + [sessionIdentifierToFetcherMap removeObjectForKey:_sessionIdentifier]; + _sessionIdentifier = nil; + _didCreateSessionIdentifier = NO; + } +} + +// External stop method +- (void)stopFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Prevent enqueued callbacks from executing. + _userStoppedFetching = YES; + } // @synchronized(self) + [self stopFetchReleasingCallbacks:YES]; +} + +// Cancel the fetch of the URL that's currently in progress. +// +// If shouldReleaseCallbacks is NO then the fetch will be retried so the callbacks +// need to still be retained. +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks { + [self removePersistedBackgroundSessionFromDefaults]; + + id service; + NSMutableURLRequest *request; + + // If the task or the retry timer is all that's retaining the fetcher, + // we want to be sure this instance survives stopping at least long enough for + // the stack to unwind. + __autoreleasing GTMSessionFetcher *holdSelf = self; + + BOOL hasCanceledTask = NO; + + [holdSelf destroyRetryTimer]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _hasStoppedFetching = YES; + + service = _service; + request = _request; + + if (_sessionTask) { + // In case cancelling the task or session calls this recursively, we want + // to ensure that we'll only release the task and delegate once, + // so first set _sessionTask to nil + // + // This may be called in a callback from the task, so use autorelease to avoid + // releasing the task in its own callback. + __autoreleasing NSURLSessionTask *oldTask = _sessionTask; + if (!_isUsingTestBlock) { + _response = _sessionTask.response; + } + _sessionTask = nil; + + if ([oldTask state] != NSURLSessionTaskStateCompleted) { + // For download tasks, when the fetch is stopped, we may provide resume data that can + // be used to create a new session. + BOOL mayResume = (_resumeDataBlock + && [oldTask respondsToSelector:@selector(cancelByProducingResumeData:)]); + if (!mayResume) { + [oldTask cancel]; + // A side effect of stopping the task is that URLSession:task:didCompleteWithError: + // will be invoked asynchronously on the delegate queue. + } else { + void (^resumeBlock)(NSData *) = _resumeDataBlock; + _resumeDataBlock = nil; + + // Save callbackQueue since releaseCallbacks clears it. + dispatch_queue_t callbackQueue = _callbackQueue; + dispatch_group_enter(_callbackGroup); + [(NSURLSessionDownloadTask *)oldTask cancelByProducingResumeData:^(NSData *resumeData) { + [self invokeOnCallbackQueue:callbackQueue + afterUserStopped:YES + block:^{ + resumeBlock(resumeData); + dispatch_group_leave(self->_callbackGroup); + }]; + }]; + } + hasCanceledTask = YES; + } + } + + // If the task was canceled, wait until the URLSession:task:didCompleteWithError: to call + // finishTasksAndInvalidate, since calling it immediately tends to crash, see radar 18471901. + if (_session) { + BOOL shouldInvalidate = _shouldInvalidateSession; +#if TARGET_OS_IPHONE + // Don't invalidate if we've got a systemCompletionHandler, since + // URLSessionDidFinishEventsForBackgroundURLSession: won't be called if invalidated. + shouldInvalidate = shouldInvalidate && !self.systemCompletionHandler; +#endif + if (shouldInvalidate) { + __autoreleasing NSURLSession *oldSession = _session; + _session = nil; + + if (!hasCanceledTask) { + [oldSession finishTasksAndInvalidate]; + } else { + _sessionNeedingInvalidation = oldSession; + } + } + } + } // @synchronized(self) + + // send the stopped notification + [self sendStopNotificationIfNeeded]; + + [_authorizer stopAuthorizationForRequest:request]; + + if (shouldReleaseCallbacks) { + [self releaseCallbacks]; + + self.authorizer = nil; + } + + [service fetcherDidStop:self]; + +#if GTM_BACKGROUND_TASK_FETCHING + [self endBackgroundTask]; +#endif +} + +- (void)setStopNotificationNeeded:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _isStopNotificationNeeded = flag; + } // @synchronized(self) +} + +- (void)sendStopNotificationIfNeeded { + BOOL sendNow = NO; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_isStopNotificationNeeded) { + _isStopNotificationNeeded = NO; + sendNow = YES; + } + } // @synchronized(self) + + if (sendNow) { + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherStoppedNotification + userInfo:nil + requireAsync:NO]; + } +} + +- (void)retryFetch { + [self stopFetchReleasingCallbacks:NO]; + + // A retry will need a configuration with a fresh session identifier. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionIdentifier && _didCreateSessionIdentifier) { + [self forgetSessionIdentifierForFetcher]; + _configuration = nil; + } + + if (_canShareSession) { + // Force a grab of the current session from the fetcher service in case + // the service's old one has become invalid. + _session = nil; + } + } // @synchronized(self) + + [self beginFetchForRetry]; +} + +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + // Uncovered in upload fetcher testing, because the chunk fetcher is being waited on, and gets + // released by the upload code. The uploader just holds onto it with an ivar, and that gets + // nilled in the chunk fetcher callback. + // Used once in while loop just to avoid unused variable compiler warning. + __autoreleasing GTMSessionFetcher *holdSelf = self; + + NSDate *giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + BOOL shouldSpinRunLoop = ([NSThread isMainThread] && + (!self.callbackQueue + || self.callbackQueue == dispatch_get_main_queue())); + BOOL expired = NO; + + // Loop until the callbacks have been called and released, and until + // the connection is no longer pending, until there are no callback dispatches + // in flight, or until the timeout has expired. + int64_t delta = (int64_t)(100 * NSEC_PER_MSEC); // 100 ms + while (1) { + BOOL isTaskInProgress = (holdSelf->_sessionTask + && [_sessionTask state] != NSURLSessionTaskStateCompleted); + BOOL needsToCallCompletion = (_completionHandler != nil); + BOOL isCallbackInProgress = (_callbackGroup + && dispatch_group_wait(_callbackGroup, dispatch_time(DISPATCH_TIME_NOW, delta))); + + if (!isTaskInProgress && !needsToCallCompletion && !isCallbackInProgress) break; + + expired = ([giveUpDate timeIntervalSinceNow] < 0); + if (expired) { + GTMSESSION_LOG_DEBUG(@"GTMSessionFetcher waitForCompletionWithTimeout:%0.1f expired -- " + @"%@%@%@", timeoutInSeconds, + isTaskInProgress ? @"taskInProgress " : @"", + needsToCallCompletion ? @"needsToCallCompletion " : @"", + isCallbackInProgress ? @"isCallbackInProgress" : @""); + break; + } + + // Run the current run loop 1/1000 of a second to give the networking + // code a chance to work + const NSTimeInterval kSpinInterval = 0.001; + if (shouldSpinRunLoop) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:kSpinInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + [NSThread sleepForTimeInterval:kSpinInterval]; + } + } + return !expired; +} + ++ (void)setGlobalTestBlock:(GTMSessionFetcherTestBlock GTM_NULLABLE_TYPE)block { +#if GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSESSION_ASSERT_DEBUG(block == nil, @"test blocks disabled"); +#endif + gGlobalTestBlock = [block copy]; +} + +#if GTM_BACKGROUND_TASK_FETCHING + +static GTM_NULLABLE_TYPE id gSubstituteUIApp; + ++ (void)setSubstituteUIApplication:(nullable id)app { + gSubstituteUIApp = app; +} + ++ (nullable id)substituteUIApplication { + return gSubstituteUIApp; +} + ++ (nullable id)fetcherUIApplication { + id app = gSubstituteUIApp; + if (app) return app; + + // iOS App extensions should not call [UIApplication sharedApplication], even + // if UIApplication responds to it. + + static Class applicationClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + BOOL isAppExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + if (!isAppExtension) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + }); + + if (applicationClass) { + app = (id)[applicationClass sharedApplication]; + } + return app; +} +#endif // GTM_BACKGROUND_TASK_FETCHING + +#pragma mark NSURLSession Delegate Methods + +// NSURLSession documentation indicates that redirectRequest can be passed to the handler +// but empirically redirectRequest lacks the HTTP body, so passing it will break POSTs. +// Instead, we construct a new request, a copy of the original, with overrides from the +// redirect. + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)redirectResponse + newRequest:(NSURLRequest *)redirectRequest + completionHandler:(void (^)(NSURLRequest * GTM_NULLABLE_TYPE))handler { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ willPerformHTTPRedirection:%@ newRequest:%@", + [self class], self, session, task, redirectResponse, redirectRequest); + + if ([self userStoppedFetching]) { + handler(nil); + return; + } + if (redirectRequest && redirectResponse) { + // Copy the original request, including the body. + NSURLRequest *originalRequest = self.request; + NSMutableURLRequest *newRequest = [originalRequest mutableCopy]; + + // The new requests's URL overrides the original's URL. + [newRequest setURL:[GTMSessionFetcher redirectURLWithOriginalRequestURL:originalRequest.URL + redirectRequestURL:redirectRequest.URL]]; + + // Any headers in the redirect override headers in the original. + NSDictionary *redirectHeaders = redirectRequest.allHTTPHeaderFields; + for (NSString *key in redirectHeaders) { + NSString *value = [redirectHeaders objectForKey:key]; + [newRequest setValue:value forHTTPHeaderField:key]; + } + + redirectRequest = newRequest; + + // Log the response we just received + [self setResponse:redirectResponse]; + [self logNowWithError:nil]; + + GTMSessionFetcherWillRedirectBlock willRedirectBlock = self.willRedirectBlock; + if (willRedirectBlock) { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + willRedirectBlock(redirectResponse, redirectRequest, ^(NSURLRequest *clientRequest) { + + // Update the request for future logging. + [self updateMutableRequest:[clientRequest mutableCopy]]; + + handler(clientRequest); + }); + }]; + } // @synchronized(self) + return; + } + // Continues here if the client did not provide a redirect block. + + // Update the request for future logging. + [self updateMutableRequest:[redirectRequest mutableCopy]]; + } + handler(redirectRequest); +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))handler { + [self setSessionTask:dataTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didReceiveResponse:%@", + [self class], self, session, dataTask, response); + void (^accumulateAndFinish)(NSURLSessionResponseDisposition) = + ^(NSURLSessionResponseDisposition dispositionValue) { + // This method is called when the server has determined that it + // has enough information to create the NSURLResponse + // it can be called multiple times, for example in the case of a + // redirect, so each time we reset the data. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL hadPreviousData = self->_downloadedLength > 0; + + [self->_downloadedData setLength:0]; + self->_downloadedLength = 0; + + if (hadPreviousData && (dispositionValue != NSURLSessionResponseCancel)) { + // Tell the accumulate block to discard prior data. + GTMSessionFetcherAccumulateDataBlock accumulateBlock = self->_accumulateDataBlock; + if (accumulateBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + accumulateBlock(nil); + }]; + } + } + } // @synchronized(self) + handler(dispositionValue); + }; + + GTMSessionFetcherDidReceiveResponseBlock receivedResponseBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + receivedResponseBlock = _didReceiveResponseBlock; + if (receivedResponseBlock) { + // We will ultimately need to call back to NSURLSession's handler with the disposition value + // for this delegate method even if the user has stopped the fetcher. + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + receivedResponseBlock(response, ^(NSURLSessionResponseDisposition desiredDisposition) { + accumulateAndFinish(desiredDisposition); + }); + }]; + } + } // @synchronized(self) + + if (receivedResponseBlock == nil) { + accumulateAndFinish(NSURLSessionResponseAllow); + } +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didBecomeDownloadTask:%@", + [self class], self, session, dataTask, downloadTask); + [self setSessionTask:downloadTask]; +} + + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential))handler { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didReceiveChallenge:%@", + [self class], self, session, task, challenge); + + GTMSessionFetcherChallengeBlock challengeBlock = self.challengeBlock; + if (challengeBlock) { + // The fetcher user has provided custom challenge handling. + // + // We will ultimately need to call back to NSURLSession's handler with the disposition value + // for this delegate method even if the user has stopped the fetcher. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + challengeBlock(self, challenge, handler); + }]; + } + } else { + // No challenge block was provided by the client. + [self respondToChallenge:challenge + completionHandler:handler]; + } +} + +- (void)respondToChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential))handler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSInteger previousFailureCount = [challenge previousFailureCount]; + if (previousFailureCount <= 2) { + NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; + NSString *authenticationMethod = [protectionSpace authenticationMethod]; + if ([authenticationMethod isEqual:NSURLAuthenticationMethodServerTrust]) { + // SSL. + // + // Background sessions seem to require an explicit check of the server trust object + // rather than default handling. + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + // No server trust information is available. + handler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } else { + // Server trust information is available. + void (^callback)(SecTrustRef, BOOL) = ^(SecTrustRef trustRef, BOOL allow){ + if (allow) { + NSURLCredential *trustCredential = [NSURLCredential credentialForTrust:trustRef]; + handler(NSURLSessionAuthChallengeUseCredential, trustCredential); + } else { + GTMSESSION_LOG_DEBUG(@"Cancelling authentication challenge for %@", self->_request.URL); + handler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + if (_allowInvalidServerCertificates) { + callback(serverTrust, YES); + } else { + [[self class] evaluateServerTrust:serverTrust + forRequest:_request + completionHandler:callback]; + } + } + return; + } + + NSURLCredential *credential = _credential; + + if ([[challenge protectionSpace] isProxy] && _proxyCredential != nil) { + credential = _proxyCredential; + } + + if (credential) { + handler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + // The credential is still nil; tell the OS to use the default handling. This is needed + // for things that can come out of the keychain (proxies, client certificates, etc.). + // + // Note: Looking up a credential with NSURLCredentialStorage's + // defaultCredentialForProtectionSpace: is *not* the same invoking the handler with + // NSURLSessionAuthChallengePerformDefaultHandling. In the case of + // NSURLAuthenticationMethodClientCertificate, you can get nil back from + // NSURLCredentialStorage, while using this code path instead works. + handler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } + + } else { + // We've failed auth 3 times. The completion handler will be called with code + // NSURLErrorCancelled. + handler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + } // @synchronized(self) +} + +// Return redirect URL based on the original request URL and redirect request URL. +// +// Method disallows any scheme changes between the original request URL and redirect request URL +// aside from "http" to "https". If a change in scheme is detected the redirect URL inherits the +// scheme from the original request URL. ++ (GTM_NULLABLE NSURL *)redirectURLWithOriginalRequestURL:(GTM_NULLABLE NSURL *)originalRequestURL + redirectRequestURL:(GTM_NULLABLE NSURL *)redirectRequestURL { + // In the case of an NSURLSession redirect, neither URL should ever be nil; as a sanity check + // if either is nil return the other URL. + if (!redirectRequestURL) return originalRequestURL; + if (!originalRequestURL) return redirectRequestURL; + + NSString *originalScheme = originalRequestURL.scheme; + NSString *redirectScheme = redirectRequestURL.scheme; + BOOL insecureToSecureRedirect = + (originalScheme != nil && [originalScheme caseInsensitiveCompare:@"http"] == NSOrderedSame && + redirectScheme != nil && [redirectScheme caseInsensitiveCompare:@"https"] == NSOrderedSame); + + // This can't really be nil for the inputs, but to keep the analyzer happy + // for the -caseInsensitiveCompare: call below, give it a value if it were. + if (!originalScheme) originalScheme = @"https"; + + // Check for changes to the scheme and disallow any changes except for http to https. + if (!insecureToSecureRedirect && + (redirectScheme.length != originalScheme.length || + [redirectScheme caseInsensitiveCompare:originalScheme] != NSOrderedSame)) { + NSURLComponents *components = + [NSURLComponents componentsWithURL:(NSURL * _Nonnull)redirectRequestURL + resolvingAgainstBaseURL:NO]; + components.scheme = originalScheme; + return components.URL; + } + + return redirectRequestURL; +} + +// Validate the certificate chain. +// +// This may become a public method if it appears to be useful to users. ++ (void)evaluateServerTrust:(SecTrustRef)serverTrust + forRequest:(NSURLRequest *)request + completionHandler:(void (^)(SecTrustRef trustRef, BOOL allow))handler { + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + // + // We must also avoid multiple uses of the trust object, per docs: + // "It is not safe to call this function concurrently with any other function that uses + // the same trust management object, or to re-enter this function for the same trust + // management object." + // + // SecTrustEvaluateAsync both does sync execution of Evaluate and calls back on the + // queue passed to it, according to at sources in + // http://www.opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55050.9/lib/SecTrust.cpp + // It would require a global serial queue to ensure the evaluate happens only on a + // single thread at a time, so we'll stick with using SecTrustEvaluate on a background + // thread. + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_async(evaluateBackgroundQueue, ^{ + // It looks like the implementation of SecTrustEvaluate() on Mac grabs a global lock, + // so it may be redundant for us to also lock, but it's easy to synchronize here + // anyway. + BOOL shouldAllow; +#if GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR + CFErrorRef errorRef = NULL; + @synchronized ([GTMSessionFetcher class]) { + GTMSessionMonitorSynchronized([GTMSessionFetcher class]); + + // SecTrustEvaluateWithError handles both the "proceed" and "unspecified" cases, + // so it is not necessary to check the trust result the evaluation returns true. + shouldAllow = SecTrustEvaluateWithError(serverTrust, &errorRef); + } + + if (errorRef) { + GTMSESSION_LOG_DEBUG(@"Error %d evaluating trust for %@", + (int)CFErrorGetCode(errorRef), request); + CFRelease(errorRef); + } +#else + SecTrustResultType trustEval = kSecTrustResultInvalid; + OSStatus trustError; + @synchronized([GTMSessionFetcher class]) { + GTMSessionMonitorSynchronized([GTMSessionFetcher class]); + + trustError = SecTrustEvaluate(serverTrust, &trustEval); + } + if (trustError != errSecSuccess) { + GTMSESSION_LOG_DEBUG(@"Error %d evaluating trust for %@", + (int)trustError, request); + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + if (trustEval == kSecTrustResultUnspecified + || trustEval == kSecTrustResultProceed) { + shouldAllow = YES; + } else { + shouldAllow = NO; + GTMSESSION_LOG_DEBUG(@"Challenge SecTrustResultType %u for %@, properties: %@", + trustEval, request.URL.host, + CFBridgingRelease(SecTrustCopyProperties(serverTrust))); + } + } +#endif // GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR + handler(serverTrust, shouldAllow); + + CFRelease(serverTrust); + }); +} + +- (void)invokeOnCallbackQueueUnlessStopped:(void (^)(void))block { + [self invokeOnCallbackQueueAfterUserStopped:NO + block:block]; +} + +- (void)invokeOnCallbackQueueAfterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + GTMSessionCheckSynchronized(self); + + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:afterStopped + block:block]; +} + +- (void)invokeOnCallbackUnsynchronizedQueueAfterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + // testBlock simulation code may not be synchronizing when this is invoked. + [self invokeOnCallbackQueue:_callbackQueue + afterUserStopped:afterStopped + block:block]; +} + +- (void)invokeOnCallbackQueue:(dispatch_queue_t)callbackQueue + afterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + if (callbackQueue) { + dispatch_group_async(_callbackGroup, callbackQueue, ^{ + if (!afterStopped) { + NSDate *serviceStoppedAllDate = [self->_service stoppedAllFetchersDate]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Avoid a race between stopFetching and the callback. + if (self->_userStoppedFetching) { + return; + } + + // Also avoid calling back if the service has stopped all fetchers + // since this one was created. The fetcher may have stopped before + // stopAllFetchers was invoked, so _userStoppedFetching wasn't set, + // but the app still won't expect the callback to fire after + // the service's stopAllFetchers was invoked. + if (serviceStoppedAllDate + && [self->_initialBeginFetchDate compare:serviceStoppedAllDate] != NSOrderedDescending) { + // stopAllFetchers was called after this fetcher began. + return; + } + } // @synchronized(self) + } + block(); + }); + } +} + +- (void)invokeFetchCallbacksOnCallbackQueueWithData:(GTM_NULLABLE NSData *)data + error:(GTM_NULLABLE NSError *)error { + // Callbacks will be released in the method stopFetchReleasingCallbacks: + GTMSessionFetcherCompletionHandler handler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + handler = _completionHandler; + + if (handler) { + [self invokeOnCallbackQueueUnlessStopped:^{ + handler(data, error); + + // Post a notification, primarily to allow code to collect responses for + // testing. + // + // The observing code is not likely on the fetcher's callback + // queue, so this posts explicitly to the main queue. + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (data) { + userInfo[kGTMSessionFetcherCompletionDataKey] = data; + } + if (error) { + userInfo[kGTMSessionFetcherCompletionErrorKey] = error; + } + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherCompletionInvokedNotification + userInfo:userInfo + requireAsync:NO]; + }]; + } + } // @synchronized(self) +} + +- (void)postNotificationOnMainThreadWithName:(NSString *)noteName + userInfo:(GTM_NULLABLE NSDictionary *)userInfo + requireAsync:(BOOL)requireAsync { + dispatch_block_t postBlock = ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:noteName + object:self + userInfo:userInfo]; + }; + + if ([NSThread isMainThread] && !requireAsync) { + // Post synchronously for compatibility with older code using the fetcher. + + // Avoid calling out to other code from inside a sync block to avoid risk + // of a deadlock or of recursive sync. + GTMSessionCheckNotSynchronized(self); + + postBlock(); + } else { + dispatch_async(dispatch_get_main_queue(), postBlock); + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)uploadTask + needNewBodyStream:(void (^)(NSInputStream * GTM_NULLABLE_TYPE bodyStream))completionHandler { + [self setSessionTask:uploadTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ needNewBodyStream:", + [self class], self, session, uploadTask); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSessionFetcherBodyStreamProvider provider = _bodyStreamProvider; +#if !STRIP_GTM_FETCH_LOGGING + if ([self respondsToSelector:@selector(loggedStreamProviderForStreamProvider:)]) { + provider = [self performSelector:@selector(loggedStreamProviderForStreamProvider:) + withObject:provider]; + } +#endif + if (provider) { + [self invokeOnCallbackQueueUnlessStopped:^{ + provider(completionHandler); + }]; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"NSURLSession expects a stream provider"); + + completionHandler(nil); + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didSendBodyData:%lld" + @" totalBytesSent:%lld totalBytesExpectedToSend:%lld", + [self class], self, session, task, bytesSent, totalBytesSent, + totalBytesExpectedToSend); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (!_sendProgressBlock) { + return; + } + // We won't hold on to send progress block; it's ok to not send it if the upload finishes. + [self invokeOnCallbackQueueUnlessStopped:^{ + GTMSessionFetcherSendProgressBlock progressBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + progressBlock = self->_sendProgressBlock; + } + if (progressBlock) { + progressBlock(bytesSent, totalBytesSent, totalBytesExpectedToSend); + } + }]; + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + [self setSessionTask:dataTask]; + NSUInteger bufferLength = data.length; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didReceiveData:%p (%llu bytes)", + [self class], self, session, dataTask, data, + (unsigned long long)bufferLength); + if (bufferLength == 0) { + // Observed on completing an out-of-process upload. + return; + } + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSessionFetcherAccumulateDataBlock accumulateBlock = _accumulateDataBlock; + if (accumulateBlock) { + // Let the client accumulate the data. + _downloadedLength += bufferLength; + [self invokeOnCallbackQueueUnlessStopped:^{ + accumulateBlock(data); + }]; + } else if (!_userStoppedFetching) { + // Append to the mutable data buffer unless the fetch has been cancelled. + + // Resumed upload tasks may not yet have a data buffer. + if (_downloadedData == nil) { + // Using NSClassFromString for iOS 6 compatibility. + GTMSESSION_ASSERT_DEBUG( + ![dataTask isKindOfClass:NSClassFromString(@"NSURLSessionDownloadTask")], + @"Resumed download tasks should not receive data bytes"); + _downloadedData = [[NSMutableData alloc] init]; + } + + [_downloadedData appendData:data]; + _downloadedLength = (int64_t)_downloadedData.length; + + // We won't hold on to receivedProgressBlock here; it's ok to not send + // it if the transfer finishes. + if (_receivedProgressBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + GTMSessionFetcherReceivedProgressBlock progressBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + progressBlock = self->_receivedProgressBlock; + } + if (progressBlock) { + progressBlock((int64_t)bufferLength, self->_downloadedLength); + } + }]; + } + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ willCacheResponse:%@ %@", + [self class], self, session, dataTask, + proposedResponse, proposedResponse.response); + GTMSessionFetcherWillCacheURLResponseBlock callback; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + callback = _willCacheURLResponseBlock; + + if (callback) { + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + callback(proposedResponse, completionHandler); + }]; + } + } // @synchronized(self) + if (!callback) { + completionHandler(proposedResponse); + } +} + + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didWriteData:(int64_t)bytesWritten + totalBytesWritten:(int64_t)totalBytesWritten +totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didWriteData:%lld" + @" bytesWritten:%lld totalBytesExpectedToWrite:%lld", + [self class], self, session, downloadTask, bytesWritten, + totalBytesWritten, totalBytesExpectedToWrite); + [self setSessionTask:downloadTask]; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if ((totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown) && + (totalBytesExpectedToWrite < totalBytesWritten)) { + // Have observed cases were bytesWritten == totalBytesExpectedToWrite, + // but totalBytesWritten > totalBytesExpectedToWrite, so setting to unkown in these cases. + totalBytesExpectedToWrite = NSURLSessionTransferSizeUnknown; + } + + GTMSessionFetcherDownloadProgressBlock progressBlock; + progressBlock = self->_downloadProgressBlock; + if (progressBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + progressBlock(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); + }]; + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didResumeAtOffset:(int64_t)fileOffset +expectedTotalBytes:(int64_t)expectedTotalBytes { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didResumeAtOffset:%lld" + @" expectedTotalBytes:%lld", + [self class], self, session, downloadTask, fileOffset, + expectedTotalBytes); + [self setSessionTask:downloadTask]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask +didFinishDownloadingToURL:(NSURL *)downloadLocationURL { + // Download may have relaunched app, so update _sessionTask. + [self setSessionTask:downloadTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didFinishDownloadingToURL:%@", + [self class], self, session, downloadTask, downloadLocationURL); + NSNumber *fileSizeNum; + [downloadLocationURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:NULL]; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURL *destinationURL = _destinationFileURL; + + _downloadedLength = fileSizeNum.longLongValue; + + // Overwrite any previous file at the destination URL. + NSFileManager *fileMgr = [NSFileManager defaultManager]; + NSError *removeError; + if (![fileMgr removeItemAtURL:destinationURL error:&removeError] + && removeError.code != NSFileNoSuchFileError) { + GTMSESSION_LOG_DEBUG(@"Could not remove previous file at %@ due to %@", + downloadLocationURL.path, removeError); + } + + NSInteger statusCode = [self statusCodeUnsynchronized]; + if (statusCode < 200 || statusCode > 399) { + // In OS X 10.11, the response body is written to a file even on a server + // status error. For convenience of the fetcher client, we'll skip saving the + // downloaded body to the destination URL so that clients do not need to know + // to delete the file following fetch errors. + GTMSESSION_LOG_DEBUG(@"Abandoning download due to status %ld, file %@", + (long)statusCode, downloadLocationURL.path); + + // On error code, add the contents of the temporary file to _downloadTaskErrorData + // This way fetcher clients have access to error details possibly passed by the server. + if (_downloadedLength > 0 && _downloadedLength <= kMaximumDownloadErrorDataLength) { + _downloadTaskErrorData = [NSData dataWithContentsOfURL:downloadLocationURL]; + } else if (_downloadedLength > kMaximumDownloadErrorDataLength) { + GTMSESSION_LOG_DEBUG(@"Download error data for file %@ not passed to userInfo due to size " + @"%lld", downloadLocationURL.path, _downloadedLength); + } + } else { + NSError *moveError; + NSURL *destinationFolderURL = [destinationURL URLByDeletingLastPathComponent]; + BOOL didMoveDownload = NO; + if ([fileMgr createDirectoryAtURL:destinationFolderURL + withIntermediateDirectories:YES + attributes:nil + error:&moveError]) { + didMoveDownload = [fileMgr moveItemAtURL:downloadLocationURL + toURL:destinationURL + error:&moveError]; + } + if (!didMoveDownload) { + _downloadFinishedError = moveError; + } + GTM_LOG_BACKGROUND_SESSION(@"%@ %p Moved download from \"%@\" to \"%@\" %@", + [self class], self, + downloadLocationURL.path, destinationURL.path, + error ? error : @""); + } + } // @synchronized(self) +} + +/* Sent as the last message related to a specific task. Error may be + * nil, which implies that no error occurred and this task is complete. + */ +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(NSError *)error { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didCompleteWithError:%@", + [self class], self, session, task, error); + + NSInteger status = self.statusCode; + BOOL forceAssumeRetry = NO; + BOOL succeeded = NO; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + // The task is never resumed when a testBlock is used. When the session is destroyed, + // we should ignore the callback, since the testBlock support code itself invokes + // shouldRetryNowForStatus: and finishWithError:shouldRetry: + if (_isUsingTestBlock) return; +#endif + + if (error == nil) { + error = _downloadFinishedError; + } + succeeded = (error == nil && status >= 0 && status < 300); + if (succeeded) { + // Succeeded. + _bodyLength = task.countOfBytesSent; + } + } // @synchronized(self) + + if (succeeded) { + [self finishWithError:nil shouldRetry:NO]; + return; + } + // For background redirects, no delegate method is called, so we cannot restore a stripped + // Authorization header, so if a 403 ("Forbidden") was generated due to a missing OAuth 2 header, + // set the current request's URL to the redirected URL, so we in effect restore the Authorization + // header. + if ((status == 403) && self.usingBackgroundSession) { + NSURL *redirectURL = self.response.URL; + NSURLRequest *request = self.request; + if (![request.URL isEqual:redirectURL]) { + NSString *authorizationHeader = [request.allHTTPHeaderFields objectForKey:@"Authorization"]; + if (authorizationHeader != nil) { + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + mutableRequest.URL = redirectURL; + [self updateMutableRequest:mutableRequest]; + // Avoid assuming the session is still valid. + self.session = nil; + forceAssumeRetry = YES; + } + } + } + + // If invalidating the session was deferred in stopFetchReleasingCallbacks: then do it now. + NSURLSession *oldSession = self.sessionNeedingInvalidation; + if (oldSession) { + [self setSessionNeedingInvalidation:NULL]; + [oldSession finishTasksAndInvalidate]; + } + + // Failed. + [self shouldRetryNowForStatus:status + error:error + forceAssumeRetry:forceAssumeRetry + response:^(BOOL shouldRetry) { + [self finishWithError:error shouldRetry:shouldRetry]; + }]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics + API_AVAILABLE(ios(10.0), macosx(10.12), tvos(10.0), watchos(3.0)) { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + GTMSessionFetcherMetricsCollectionBlock metricsCollectionBlock = _metricsCollectionBlock; + if (metricsCollectionBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + metricsCollectionBlock(metrics); + }]; + } + } +} + +#if TARGET_OS_IPHONE +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSessionDidFinishEventsForBackgroundURLSession:%@", + [self class], self, session); + [self removePersistedBackgroundSessionFromDefaults]; + + GTMSessionFetcherSystemCompletionHandler handler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + handler = self.systemCompletionHandler; + self.systemCompletionHandler = nil; + } // @synchronized(self) + if (handler) { + GTM_LOG_BACKGROUND_SESSION(@"%@ %p Calling system completionHandler", [self class], self); + handler(); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLSession *oldSession = _session; + _session = nil; + if (_shouldInvalidateSession) { + [oldSession finishTasksAndInvalidate]; + } + } // @synchronized(self) + } +} +#endif + +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(GTM_NULLABLE NSError *)error { + // This may happen repeatedly for retries. On authentication callbacks, the retry + // may begin before the prior session sends the didBecomeInvalid delegate message. + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ didBecomeInvalidWithError:%@", + [self class], self, session, error); + if (session == (NSURLSession *)self.session) { + GTM_LOG_SESSION_DELEGATE(@" Unexpected retained invalid session: %@", session); + self.session = nil; + } +} + +- (void)finishWithError:(GTM_NULLABLE NSError *)error shouldRetry:(BOOL)shouldRetry { + [self removePersistedBackgroundSessionFromDefaults]; + + BOOL shouldStopFetching = YES; + NSData *downloadedData = nil; +#if !STRIP_GTM_FETCH_LOGGING + BOOL shouldDeferLogging = NO; +#endif + BOOL shouldBeginRetryTimer = NO; + NSInteger status = [self statusCode]; + NSURL *destinationURL = self.destinationFileURL; + + BOOL fetchSucceeded = (error == nil && status >= 0 && status < 300); + +#if !STRIP_GTM_FETCH_LOGGING + if (!fetchSucceeded) { + if (!shouldDeferLogging && !self.hasLoggedError) { + [self logNowWithError:error]; + self.hasLoggedError = YES; + } + } +#endif // !STRIP_GTM_FETCH_LOGGING + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + +#if !STRIP_GTM_FETCH_LOGGING + shouldDeferLogging = _deferResponseBodyLogging; +#endif + if (fetchSucceeded) { + // Success + if ((_downloadedData.length > 0) && (destinationURL != nil)) { + // Overwrite any previous file at the destination URL. + NSFileManager *fileMgr = [NSFileManager defaultManager]; + [fileMgr removeItemAtURL:destinationURL + error:NULL]; + NSURL *destinationFolderURL = [destinationURL URLByDeletingLastPathComponent]; + BOOL didMoveDownload = NO; + if ([fileMgr createDirectoryAtURL:destinationFolderURL + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + didMoveDownload = [_downloadedData writeToURL:destinationURL + options:NSDataWritingAtomic + error:&error]; + } + if (didMoveDownload) { + _downloadedData = nil; + } else { + _downloadFinishedError = error; + } + } + downloadedData = _downloadedData; + } else { + // Unsuccessful with error or status over 300. Retry or notify the delegate of failure + if (shouldRetry) { + // Retrying. + shouldBeginRetryTimer = YES; + shouldStopFetching = NO; + } else { + if (error == nil) { + // Create an error. + NSDictionary *userInfo = GTMErrorUserInfoForData( + _downloadedData.length > 0 ? _downloadedData : _downloadTaskErrorData, + [self responseHeadersUnsynchronized]); + + error = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:status + userInfo:userInfo]; + } else { + // If the error had resume data, and the client supplied a resume block, pass the + // data to the client. + void (^resumeBlock)(NSData *) = _resumeDataBlock; + _resumeDataBlock = nil; + if (resumeBlock) { + NSData *resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]; + if (resumeData) { + [self invokeOnCallbackQueueAfterUserStopped:YES block:^{ + resumeBlock(resumeData); + }]; + } + } + } + if (_downloadedData.length > 0) { + downloadedData = _downloadedData; + } + // If the error occurred after retries, report the number and duration of the + // retries. This provides a clue to a developer looking at the error description + // that the fetcher did retry before failing with this error. + if (_retryCount > 0) { + NSMutableDictionary *userInfoWithRetries = + [NSMutableDictionary dictionaryWithDictionary:(NSDictionary *)error.userInfo]; + NSTimeInterval timeSinceInitialRequest = -[_initialRequestDate timeIntervalSinceNow]; + [userInfoWithRetries setObject:@(timeSinceInitialRequest) + forKey:kGTMSessionFetcherElapsedIntervalWithRetriesKey]; + [userInfoWithRetries setObject:@(_retryCount) + forKey:kGTMSessionFetcherNumberOfRetriesDoneKey]; + error = [NSError errorWithDomain:(NSString *)error.domain + code:error.code + userInfo:userInfoWithRetries]; + } + } + } + } // @synchronized(self) + + if (shouldBeginRetryTimer) { + [self beginRetryTimer]; + } + + // We want to send the stop notification before calling the delegate's + // callback selector, since the callback selector may release all of + // the fetcher properties that the client is using to track the fetches. + // + // We'll also stop now so that, to any observers watching the notifications, + // it doesn't look like our wait for a retry (which may be long, + // 30 seconds or more) is part of the network activity. + [self sendStopNotificationIfNeeded]; + + if (shouldStopFetching) { + [self invokeFetchCallbacksOnCallbackQueueWithData:downloadedData + error:error]; + // The upload subclass doesn't want to release callbacks until upload chunks have completed. + BOOL shouldRelease = [self shouldReleaseCallbacksUponCompletion]; + [self stopFetchReleasingCallbacks:shouldRelease]; + } + +#if !STRIP_GTM_FETCH_LOGGING + // _hasLoggedError is only set by this method + if (!shouldDeferLogging && !_hasLoggedError) { + [self logNowWithError:error]; + } +#endif +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // A subclass can override this to keep callbacks around after the + // connection has finished successfully + return YES; +} + +- (void)logNowWithError:(GTM_NULLABLE NSError *)error { + GTMSessionCheckNotSynchronized(self); + + // If the logging category is available, then log the current request, + // response, data, and error + if ([self respondsToSelector:@selector(logFetchWithError:)]) { + [self performSelector:@selector(logFetchWithError:) withObject:error]; + } +} + +#pragma mark Retries + +- (BOOL)isRetryError:(NSError *)error { + struct RetryRecord { + __unsafe_unretained NSString *const domain; + NSInteger code; + }; + + struct RetryRecord retries[] = { + { kGTMSessionFetcherStatusDomain, 408 }, // request timeout + { kGTMSessionFetcherStatusDomain, 502 }, // failure gatewaying to another server + { kGTMSessionFetcherStatusDomain, 503 }, // service unavailable + { kGTMSessionFetcherStatusDomain, 504 }, // request timeout + { NSURLErrorDomain, NSURLErrorTimedOut }, + { NSURLErrorDomain, NSURLErrorNetworkConnectionLost }, + { nil, 0 } + }; + + // NSError's isEqual always returns false for equal but distinct instances + // of NSError, so we have to compare the domain and code values explicitly + NSString *domain = error.domain; + NSInteger code = error.code; + for (int idx = 0; retries[idx].domain != nil; idx++) { + if (code == retries[idx].code && [domain isEqual:retries[idx].domain]) { + return YES; + } + } + return NO; +} + +// shouldRetryNowForStatus:error: responds with YES if the user has enabled retries +// and the status or error is one that is suitable for retrying. "Suitable" +// means either the isRetryError:'s list contains the status or error, or the +// user's retry block is present and returns YES when called, or the +// authorizer may be able to fix. +- (void)shouldRetryNowForStatus:(NSInteger)status + error:(NSError *)error + forceAssumeRetry:(BOOL)forceAssumeRetry + response:(GTMSessionFetcherRetryResponse)response { + // Determine if a refreshed authorizer may avoid an authorization error + BOOL willRetry = NO; + + // We assume _authorizer is immutable after beginFetch, and _hasAttemptedAuthRefresh is modified + // only in this method, and this method is invoked on the serial delegate queue. + // + // We want to avoid calling the authorizer from inside a sync block. + BOOL isFirstAuthError = (_authorizer != nil + && !_hasAttemptedAuthRefresh + && status == GTMSessionFetcherStatusUnauthorized); // 401 + + BOOL hasPrimed = NO; + if (isFirstAuthError) { + if ([_authorizer respondsToSelector:@selector(primeForRefresh)]) { + hasPrimed = [_authorizer primeForRefresh]; + } + } + + BOOL shouldRetryForAuthRefresh = NO; + if (hasPrimed) { + shouldRetryForAuthRefresh = YES; + _hasAttemptedAuthRefresh = YES; + [self updateRequestValue:nil forHTTPHeaderField:@"Authorization"]; + } + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL shouldDoRetry = [self isRetryEnabledUnsynchronized]; + if (shouldDoRetry && ![self hasRetryAfterInterval]) { + + // Determine if we're doing exponential backoff retries + shouldDoRetry = [self nextRetryIntervalUnsynchronized] < _maxRetryInterval; + + if (shouldDoRetry) { + // If an explicit max retry interval was set, we expect repeated backoffs to take + // up to roughly twice that for repeated fast failures. If the initial attempt is + // already more than 3 times the max retry interval, then failures have taken a long time + // (such as from network timeouts) so don't retry again to avoid the app becoming + // unexpectedly unresponsive. + if (_maxRetryInterval > 0) { + NSTimeInterval maxAllowedIntervalBeforeRetry = _maxRetryInterval * 3; + NSTimeInterval timeSinceInitialRequest = -[_initialRequestDate timeIntervalSinceNow]; + if (timeSinceInitialRequest > maxAllowedIntervalBeforeRetry) { + shouldDoRetry = NO; + } + } + } + } + BOOL canRetry = shouldRetryForAuthRefresh || forceAssumeRetry || shouldDoRetry; + if (canRetry) { + NSDictionary *userInfo = + GTMErrorUserInfoForData(_downloadedData, [self responseHeadersUnsynchronized]); + NSError *statusError = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:status + userInfo:userInfo]; + if (error == nil) { + error = statusError; + } + willRetry = shouldRetryForAuthRefresh || + forceAssumeRetry || + [self isRetryError:error] || + ((error != statusError) && [self isRetryError:statusError]); + + // If the user has installed a retry callback, consult that. + GTMSessionFetcherRetryBlock retryBlock = _retryBlock; + if (retryBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + retryBlock(willRetry, error, response); + }]; + return; + } + } + } // @synchronized(self) + response(willRetry); +} + +- (BOOL)hasRetryAfterInterval { + GTMSessionCheckSynchronized(self); + + NSDictionary *responseHeaders = [self responseHeadersUnsynchronized]; + NSString *retryAfterValue = [responseHeaders valueForKey:@"Retry-After"]; + return (retryAfterValue != nil); +} + +- (NSTimeInterval)retryAfterInterval { + GTMSessionCheckSynchronized(self); + + NSDictionary *responseHeaders = [self responseHeadersUnsynchronized]; + NSString *retryAfterValue = [responseHeaders valueForKey:@"Retry-After"]; + if (retryAfterValue == nil) { + return 0; + } + // Retry-After formatted as HTTP-date | delta-seconds + // Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + NSDateFormatter *rfc1123DateFormatter = [[NSDateFormatter alloc] init]; + rfc1123DateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + rfc1123DateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; + rfc1123DateFormatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss z"; + NSDate *retryAfterDate = [rfc1123DateFormatter dateFromString:retryAfterValue]; + NSTimeInterval retryAfterInterval = (retryAfterDate != nil) ? + retryAfterDate.timeIntervalSinceNow : retryAfterValue.intValue; + retryAfterInterval = MAX(0, retryAfterInterval); + return retryAfterInterval; +} + +- (void)beginRetryTimer { + if (![NSThread isMainThread]) { + // Defer creating and starting the timer until we're on the main thread to ensure it has + // a run loop. + dispatch_group_async(_callbackGroup, dispatch_get_main_queue(), ^{ + [self beginRetryTimer]; + }); + return; + } + + [self destroyRetryTimer]; + +#if GTM_BACKGROUND_TASK_FETCHING + // Don't keep a background task active while awaiting retry, which can lead to the + // app exceeding the allotted time for keeping the background task open, causing the + // system to terminate the app. When the retry starts, a new background task will + // be created. + [self endBackgroundTask]; +#endif // GTM_BACKGROUND_TASK_FETCHING + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSTimeInterval nextInterval = [self nextRetryIntervalUnsynchronized]; + NSTimeInterval maxInterval = _maxRetryInterval; + NSTimeInterval newInterval = MIN(nextInterval, (maxInterval > 0 ? maxInterval : DBL_MAX)); + NSTimeInterval newIntervalTolerance = (newInterval / 10) > 1.0 ?: 1.0; + + _lastRetryInterval = newInterval; + + _retryTimer = [NSTimer timerWithTimeInterval:newInterval + target:self + selector:@selector(retryTimerFired:) + userInfo:nil + repeats:NO]; + _retryTimer.tolerance = newIntervalTolerance; + [[NSRunLoop mainRunLoop] addTimer:_retryTimer + forMode:NSDefaultRunLoopMode]; + } // @synchronized(self) + + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherRetryDelayStartedNotification + userInfo:nil + requireAsync:NO]; +} + +- (void)retryTimerFired:(NSTimer *)timer { + [self destroyRetryTimer]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _retryCount++; + } // @synchronized(self) + + NSOperationQueue *queue = self.sessionDelegateQueue; + [queue addOperationWithBlock:^{ + [self retryFetch]; + }]; +} + +- (void)destroyRetryTimer { + BOOL shouldNotify = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_retryTimer) { + [_retryTimer invalidate]; + _retryTimer = nil; + shouldNotify = YES; + } + } + + if (shouldNotify) { + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherRetryDelayStoppedNotification + userInfo:nil + requireAsync:NO]; + } +} + +- (NSUInteger)retryCount { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _retryCount; + } // @synchronized(self) +} + +- (NSTimeInterval)nextRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSTimeInterval interval = [self nextRetryIntervalUnsynchronized]; + return interval; + } // @synchronized(self) +} + +- (NSTimeInterval)nextRetryIntervalUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSInteger statusCode = [self statusCodeUnsynchronized]; + if ((statusCode == 503) && [self hasRetryAfterInterval]) { + NSTimeInterval secs = [self retryAfterInterval]; + return secs; + } + // The next wait interval is the factor (2.0) times the last interval, + // but never less than the minimum interval. + NSTimeInterval secs = _lastRetryInterval * _retryFactor; + if (_maxRetryInterval > 0) { + secs = MIN(secs, _maxRetryInterval); + } + secs = MAX(secs, _minRetryInterval); + + return secs; +} + +- (NSTimer *)retryTimer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _retryTimer; + } // @synchronized(self) +} + +- (BOOL)isRetryEnabled { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isRetryEnabled; + } // @synchronized(self) +} + +- (BOOL)isRetryEnabledUnsynchronized { + GTMSessionCheckSynchronized(self); + + return _isRetryEnabled; +} + +- (void)setRetryEnabled:(BOOL)flag { + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag && !_isRetryEnabled) { + // We defer initializing these until the user calls setRetryEnabled + // to avoid using the random number generator if it's not needed. + // However, this means min and max intervals for this fetcher are reset + // as a side effect of calling setRetryEnabled. + // + // Make an initial retry interval random between 1.0 and 2.0 seconds + _minRetryInterval = InitialMinRetryInterval(); + _maxRetryInterval = kUnsetMaxRetryInterval; + _retryFactor = 2.0; + _lastRetryInterval = 0.0; + } + _isRetryEnabled = flag; + } // @synchronized(self) +}; + +- (NSTimeInterval)maxRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _maxRetryInterval; + } // @synchronized(self) +} + +- (void)setMaxRetryInterval:(NSTimeInterval)secs { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (secs > 0) { + _maxRetryInterval = secs; + } else { + _maxRetryInterval = kUnsetMaxRetryInterval; + } + } // @synchronized(self) +} + +- (double)minRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _minRetryInterval; + } // @synchronized(self) +} + +- (void)setMinRetryInterval:(NSTimeInterval)secs { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (secs > 0) { + _minRetryInterval = secs; + } else { + // Set min interval to a random value between 1.0 and 2.0 seconds + // so that if multiple clients start retrying at the same time, they'll + // repeat at different times and avoid overloading the server + _minRetryInterval = InitialMinRetryInterval(); + } + } // @synchronized(self) + +} + +#pragma mark iOS System Completion Handlers + +#if TARGET_OS_IPHONE +static NSMutableDictionary *gSystemCompletionHandlers = nil; + +- (GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler { + return [[self class] systemCompletionHandlerForSessionIdentifier:_sessionIdentifier]; +} + +- (void)setSystemCompletionHandler:(GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler { + [[self class] setSystemCompletionHandler:systemCompletionHandler + forSessionIdentifier:_sessionIdentifier]; +} + ++ (void)setSystemCompletionHandler:(GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler + forSessionIdentifier:(NSString *)sessionIdentifier { + if (!sessionIdentifier) { + NSLog(@"%s with nil identifier", __PRETTY_FUNCTION__); + return; + } + + @synchronized([GTMSessionFetcher class]) { + if (gSystemCompletionHandlers == nil && systemCompletionHandler != nil) { + gSystemCompletionHandlers = [[NSMutableDictionary alloc] init]; + } + // Use setValue: to remove the object if completionHandler is nil. + [gSystemCompletionHandlers setValue:systemCompletionHandler + forKey:sessionIdentifier]; + } +} + ++ (GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandlerForSessionIdentifier:(NSString *)sessionIdentifier { + if (!sessionIdentifier) { + return nil; + } + @synchronized([GTMSessionFetcher class]) { + return [gSystemCompletionHandlers objectForKey:sessionIdentifier]; + } +} +#endif // TARGET_OS_IPHONE + +#pragma mark Getters and Setters + +@synthesize downloadResumeData = _downloadResumeData, + configuration = _configuration, + configurationBlock = _configurationBlock, + sessionTask = _sessionTask, + wasCreatedFromBackgroundSession = _wasCreatedFromBackgroundSession, + sessionUserInfo = _sessionUserInfo, + taskDescription = _taskDescription, + taskPriority = _taskPriority, + usingBackgroundSession = _usingBackgroundSession, + canShareSession = _canShareSession, + completionHandler = _completionHandler, + credential = _credential, + proxyCredential = _proxyCredential, + bodyData = _bodyData, + bodyLength = _bodyLength, + service = _service, + serviceHost = _serviceHost, + accumulateDataBlock = _accumulateDataBlock, + receivedProgressBlock = _receivedProgressBlock, + downloadProgressBlock = _downloadProgressBlock, + resumeDataBlock = _resumeDataBlock, + didReceiveResponseBlock = _didReceiveResponseBlock, + challengeBlock = _challengeBlock, + willRedirectBlock = _willRedirectBlock, + sendProgressBlock = _sendProgressBlock, + willCacheURLResponseBlock = _willCacheURLResponseBlock, + retryBlock = _retryBlock, + metricsCollectionBlock = _metricsCollectionBlock, + retryFactor = _retryFactor, + allowedInsecureSchemes = _allowedInsecureSchemes, + allowLocalhostRequest = _allowLocalhostRequest, + allowInvalidServerCertificates = _allowInvalidServerCertificates, + cookieStorage = _cookieStorage, + callbackQueue = _callbackQueue, + initialBeginFetchDate = _initialBeginFetchDate, + testBlock = _testBlock, + testBlockAccumulateDataChunkCount = _testBlockAccumulateDataChunkCount, + comment = _comment, + log = _log; + +#if !STRIP_GTM_FETCH_LOGGING +@synthesize redirectedFromURL = _redirectedFromURL, + logRequestBody = _logRequestBody, + logResponseBody = _logResponseBody, + hasLoggedError = _hasLoggedError; +#endif + +#if GTM_BACKGROUND_TASK_FETCHING +@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier, + skipBackgroundTask = _skipBackgroundTask; +#endif + +- (GTM_NULLABLE NSURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_request copy]; + } // @synchronized(self) +} + +- (void)setRequest:(GTM_NULLABLE NSURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (![self isFetchingUnsynchronized]) { + _request = [request mutableCopy]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"request may not be set after beginFetch has been invoked"); + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSMutableURLRequest *)mutableRequestForTesting { + // Allow tests only to modify the request, useful during retries. + return _request; +} + +// Internal method for updating the request property such as on redirects. +- (void)updateMutableRequest:(GTM_NULLABLE NSMutableURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _request = request; + } // @synchronized(self) +} + +// Set a header field value on the request. Header field value changes will not +// affect a fetch after the fetch has begun. +- (void)setRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field { + if (![self isFetching]) { + [self updateRequestValue:value forHTTPHeaderField:field]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"request may not be set after beginFetch has been invoked"); + } +} + +// Internal method for updating request headers. +- (void)updateRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_request setValue:value forHTTPHeaderField:field]; + } // @synchronized(self) +} + +- (void)setResponse:(GTM_NULLABLE NSURLResponse *)response { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _response = response; + } // @synchronized(self) +} + +- (int64_t)bodyLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_bodyLength == NSURLSessionTransferSizeUnknown) { + if (_bodyData) { + _bodyLength = (int64_t)_bodyData.length; + } else if (_bodyFileURL) { + NSNumber *fileSizeNum = nil; + NSError *fileSizeError = nil; + if ([_bodyFileURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:&fileSizeError]) { + _bodyLength = [fileSizeNum longLongValue]; + } + } + } + return _bodyLength; + } // @synchronized(self) +} + +- (BOOL)useUploadTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _useUploadTask; + } // @synchronized(self) +} + +- (void)setUseUploadTask:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag != _useUploadTask) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"useUploadTask should not change after beginFetch has been invoked"); + _useUploadTask = flag; + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURL *)bodyFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _bodyFileURL; + } // @synchronized(self) +} + +- (void)setBodyFileURL:(GTM_NULLABLE NSURL *)fileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // The comparison here is a trivial optimization and forgiveness for any client that + // repeatedly sets the property, so it just uses pointer comparison rather than isEqual:. + if (fileURL != _bodyFileURL) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"fileURL should not change after beginFetch has been invoked"); + + _bodyFileURL = fileURL; + } + } // @synchronized(self) +} + +- (GTM_NULLABLE GTMSessionFetcherBodyStreamProvider)bodyStreamProvider { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _bodyStreamProvider; + } // @synchronized(self) +} + +- (void)setBodyStreamProvider:(GTM_NULLABLE GTMSessionFetcherBodyStreamProvider)block { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"stream provider should not change after beginFetch has been invoked"); + + _bodyStreamProvider = [block copy]; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _authorizer; + } // @synchronized(self) +} + +- (void)setAuthorizer:(GTM_NULLABLE id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (authorizer != _authorizer) { + if ([self isFetchingUnsynchronized]) { + GTMSESSION_ASSERT_DEBUG(0, @"authorizer should not change after beginFetch has been invoked"); + } else { + _authorizer = authorizer; + } + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSData *)downloadedData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _downloadedData; + } // @synchronized(self) +} + +- (void)setDownloadedData:(GTM_NULLABLE NSData *)data { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _downloadedData = [data mutableCopy]; + } // @synchronized(self) +} + +- (int64_t)downloadedLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _downloadedLength; + } // @synchronized(self) +} + +- (void)setDownloadedLength:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _downloadedLength = length; + } // @synchronized(self) +} + +- (dispatch_queue_t GTM_NONNULL_TYPE)callbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _callbackQueue; + } // @synchronized(self) +} + +- (void)setCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _callbackQueue = queue ?: dispatch_get_main_queue(); + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _session; + } // @synchronized(self) +} + +- (NSInteger)servicePriority { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _servicePriority; + } // @synchronized(self) +} + +- (void)setServicePriority:(NSInteger)value { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (value != _servicePriority) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"servicePriority should not change after beginFetch has been invoked"); + + _servicePriority = value; + } + } // @synchronized(self) +} + + +- (void)setSession:(GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = session; + } // @synchronized(self) +} + +- (BOOL)canShareSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _canShareSession; + } // @synchronized(self) +} + +- (void)setCanShareSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _canShareSession = flag; + } // @synchronized(self) +} + +- (BOOL)useBackgroundSession { + // This reflects if the user requested a background session, not necessarily + // if one was created. That is tracked with _usingBackgroundSession. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userRequestedBackgroundSession; + } // @synchronized(self) +} + +- (void)setUseBackgroundSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag != _userRequestedBackgroundSession) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"useBackgroundSession should not change after beginFetch has been invoked"); + + _userRequestedBackgroundSession = flag; + } + } // @synchronized(self) +} + +- (BOOL)isUsingBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _usingBackgroundSession; + } // @synchronized(self) +} + +- (void)setUsingBackgroundSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _usingBackgroundSession = flag; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURLSession *)sessionNeedingInvalidation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionNeedingInvalidation; + } // @synchronized(self) +} + +- (void)setSessionNeedingInvalidation:(GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _sessionNeedingInvalidation = session; + } // @synchronized(self) +} + +- (NSOperationQueue * GTM_NONNULL_TYPE)sessionDelegateQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateQueue; + } // @synchronized(self) +} + +- (void)setSessionDelegateQueue:(NSOperationQueue * GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (queue != _delegateQueue) { + if ([self isFetchingUnsynchronized]) { + GTMSESSION_ASSERT_DEBUG(0, @"sessionDelegateQueue should not change after fetch begins"); + } else { + _delegateQueue = queue ?: [NSOperationQueue mainQueue]; + } + } + } // @synchronized(self) +} + +- (BOOL)userStoppedFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userStoppedFetching; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)userData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userData; + } // @synchronized(self) +} + +- (void)setUserData:(GTM_NULLABLE id)theObj { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _userData = theObj; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURL *)destinationFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _destinationFileURL; + } // @synchronized(self) +} + +- (void)setDestinationFileURL:(GTM_NULLABLE NSURL *)destinationFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (((_destinationFileURL == nil) && (destinationFileURL == nil)) || + [_destinationFileURL isEqual:destinationFileURL]) { + return; + } + if (_sessionIdentifier) { + // This is something we don't expect to happen in production. + // However if it ever happen, leave a system log. + NSLog(@"%@: Destination File URL changed from (%@) to (%@) after session identifier has " + @"been created.", + [self class], _destinationFileURL, destinationFileURL); +#if DEBUG + // On both the simulator and devices, the path can change to the download file, but the name + // shouldn't change. Technically, this isn't supported in the fetcher, but the change of + // URL is expected to happen only across development runs through Xcode. + NSString *oldFilename = [_destinationFileURL lastPathComponent]; + NSString *newFilename = [destinationFileURL lastPathComponent]; + #pragma unused(oldFilename) + #pragma unused(newFilename) + GTMSESSION_ASSERT_DEBUG([oldFilename isEqualToString:newFilename], + @"Destination File URL cannot be changed after session identifier has been created"); +#endif + } + _destinationFileURL = destinationFileURL; + } // @synchronized(self) +} + +- (void)setProperties:(GTM_NULLABLE NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _properties = [dict mutableCopy]; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSDictionary *)properties { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _properties; + } // @synchronized(self) +} + +- (void)setProperty:(GTM_NULLABLE id)obj forKey:(NSString *)key { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_properties == nil && obj != nil) { + _properties = [[NSMutableDictionary alloc] init]; + } + [_properties setValue:obj forKey:key]; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)propertyForKey:(NSString *)key { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_properties objectForKey:key]; + } // @synchronized(self) +} + +- (void)addPropertiesFromDictionary:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_properties == nil && dict != nil) { + [self setProperties:[dict mutableCopy]]; + } else { + [_properties addEntriesFromDictionary:dict]; + } + } // @synchronized(self) +} + +- (void)setCommentWithFormat:(id)format, ... { +#if !STRIP_GTM_FETCH_LOGGING + NSString *result = format; + if (format) { + va_list argList; + va_start(argList, format); + + result = [[NSString alloc] initWithFormat:format + arguments:argList]; + va_end(argList); + } + [self setComment:result]; +#endif +} + +#if !STRIP_GTM_FETCH_LOGGING +- (NSData *)loggedStreamData { + return _loggedStreamData; +} + +- (void)appendLoggedStreamData:dataToAdd { + if (!_loggedStreamData) { + _loggedStreamData = [NSMutableData data]; + } + [_loggedStreamData appendData:dataToAdd]; +} + +- (void)clearLoggedStreamData { + _loggedStreamData = nil; +} + +- (void)setDeferResponseBodyLogging:(BOOL)deferResponseBodyLogging { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (deferResponseBodyLogging != _deferResponseBodyLogging) { + _deferResponseBodyLogging = deferResponseBodyLogging; + if (!deferResponseBodyLogging && !self.hasLoggedError) { + [_delegateQueue addOperationWithBlock:^{ + [self logNowWithError:nil]; + }]; + } + } + } // @synchronized(self) +} + +- (BOOL)deferResponseBodyLogging { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _deferResponseBodyLogging; + } // @synchronized(self) +} + +#else ++ (void)setLoggingEnabled:(BOOL)flag { +} + ++ (BOOL)isLoggingEnabled { + return NO; +} +#endif // STRIP_GTM_FETCH_LOGGING + +@end + +@implementation GTMSessionFetcher (BackwardsCompatibilityOnly) + +- (void)setCookieStorageMethod:(NSInteger)method { + // For backwards compatibility with the old fetcher, we'll support the old constants. + // + // Clients using the GTMSessionFetcher class should set the cookie storage explicitly + // themselves. + NSHTTPCookieStorage *storage = nil; + switch(method) { + case 0: // kGTMHTTPFetcherCookieStorageMethodStatic + // nil storage will use [[self class] staticCookieStorage] when the fetch begins. + break; + case 1: // kGTMHTTPFetcherCookieStorageMethodFetchHistory + // Do nothing; use whatever was set by the fetcher service. + return; + case 2: // kGTMHTTPFetcherCookieStorageMethodSystemDefault + storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + break; + case 3: // kGTMHTTPFetcherCookieStorageMethodNone + // Create temporary storage for this fetcher only. + storage = [[GTMSessionCookieStorage alloc] init]; + break; + default: + GTMSESSION_ASSERT_DEBUG(0, @"Invalid cookie storage method: %d", (int)method); + } + self.cookieStorage = storage; +} + +@end + +@implementation GTMSessionCookieStorage { + NSMutableArray *_cookies; + NSHTTPCookieAcceptPolicy _policy; +} + +- (id)init { + self = [super init]; + if (self != nil) { + _cookies = [[NSMutableArray alloc] init]; + } + return self; +} + +- (GTM_NULLABLE NSArray *)cookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_cookies copy]; + } // @synchronized(self) +} + +- (void)setCookie:(NSHTTPCookie *)cookie { + if (!cookie) return; + if (_policy == NSHTTPCookieAcceptPolicyNever) return; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self internalSetCookie:cookie]; + } // @synchronized(self) +} + +// Note: this should only be called from inside a @synchronized(self) block. +- (void)internalSetCookie:(NSHTTPCookie *)newCookie { + GTMSessionCheckSynchronized(self); + + if (_policy == NSHTTPCookieAcceptPolicyNever) return; + + BOOL isValidCookie = (newCookie.name.length > 0 + && newCookie.domain.length > 0 + && newCookie.path.length > 0); + GTMSESSION_ASSERT_DEBUG(isValidCookie, @"invalid cookie: %@", newCookie); + + if (isValidCookie) { + // Remove the cookie if it's currently in the array. + NSHTTPCookie *oldCookie = [self cookieMatchingCookie:newCookie]; + if (oldCookie) { + [_cookies removeObjectIdenticalTo:oldCookie]; + } + + if (![[self class] hasCookieExpired:newCookie]) { + [_cookies addObject:newCookie]; + } + } +} + +// Add all cookies in the new cookie array to the storage, +// replacing stored cookies as appropriate. +// +// Side effect: removes expired cookies from the storage array. +- (void)setCookies:(GTM_NULLABLE NSArray *)newCookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self removeExpiredCookies]; + + for (NSHTTPCookie *newCookie in newCookies) { + [self internalSetCookie:newCookie]; + } + } // @synchronized(self) +} + +- (void)setCookies:(NSArray *)cookies forURL:(GTM_NULLABLE NSURL *)URL mainDocumentURL:(GTM_NULLABLE NSURL *)mainDocumentURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_policy == NSHTTPCookieAcceptPolicyNever) { + return; + } + + if (_policy == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain) { + NSString *mainHost = mainDocumentURL.host; + NSString *associatedHost = URL.host; + if (!mainHost || ![associatedHost hasSuffix:mainHost]) { + return; + } + } + } // @synchronized(self) + [self setCookies:cookies]; +} + +- (void)deleteCookie:(NSHTTPCookie *)cookie { + if (!cookie) return; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSHTTPCookie *foundCookie = [self cookieMatchingCookie:cookie]; + if (foundCookie) { + [_cookies removeObjectIdenticalTo:foundCookie]; + } + } // @synchronized(self) +} + +// Retrieve all cookies appropriate for the given URL, considering +// domain, path, cookie name, expiration, security setting. +// Side effect: removed expired cookies from the storage array. +- (GTM_NULLABLE NSArray *)cookiesForURL:(NSURL *)theURL { + NSMutableArray *foundCookies = nil; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self removeExpiredCookies]; + + // We'll prepend "." to the desired domain, since we want the + // actual domain "nytimes.com" to still match the cookie domain + // ".nytimes.com" when we check it below with hasSuffix. + NSString *host = theURL.host.lowercaseString; + NSString *path = theURL.path; + NSString *scheme = [theURL scheme]; + + NSString *requestingDomain = nil; + BOOL isLocalhostRetrieval = NO; + + if (IsLocalhost(host)) { + isLocalhostRetrieval = YES; + } else { + if (host.length > 0) { + requestingDomain = [@"." stringByAppendingString:host]; + } + } + + for (NSHTTPCookie *storedCookie in _cookies) { + NSString *cookieDomain = storedCookie.domain.lowercaseString; + NSString *cookiePath = storedCookie.path; + BOOL cookieIsSecure = [storedCookie isSecure]; + + BOOL isDomainOK; + + if (isLocalhostRetrieval) { + // Prior to 10.5.6, the domain stored into NSHTTPCookies for localhost + // is "localhost.local" + isDomainOK = (IsLocalhost(cookieDomain) + || [cookieDomain isEqual:@"localhost.local"]); + } else { + // Ensure we're matching exact domain names. We prepended a dot to the + // requesting domain, so we can also prepend one here if needed before + // checking if the request contains the cookie domain. + if (![cookieDomain hasPrefix:@"."]) { + cookieDomain = [@"." stringByAppendingString:cookieDomain]; + } + isDomainOK = [requestingDomain hasSuffix:cookieDomain]; + } + + BOOL isPathOK = [cookiePath isEqual:@"/"] || [path hasPrefix:cookiePath]; + BOOL isSecureOK = (!cookieIsSecure + || [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame); + + if (isDomainOK && isPathOK && isSecureOK) { + if (foundCookies == nil) { + foundCookies = [NSMutableArray array]; + } + [foundCookies addObject:storedCookie]; + } + } + } // @synchronized(self) + return foundCookies; +} + +// Override methods from the NSHTTPCookieStorage (NSURLSessionTaskAdditions) category. +- (void)storeCookies:(NSArray *)cookies forTask:(NSURLSessionTask *)task { + NSURLRequest *currentRequest = task.currentRequest; + [self setCookies:cookies forURL:currentRequest.URL mainDocumentURL:nil]; +} + +- (void)getCookiesForTask:(NSURLSessionTask *)task + completionHandler:(void (^)(GTM_NSArrayOf(NSHTTPCookie *) *))completionHandler { + if (completionHandler) { + NSURLRequest *currentRequest = task.currentRequest; + NSURL *currentRequestURL = currentRequest.URL; + NSArray *cookies = [self cookiesForURL:currentRequestURL]; + completionHandler(cookies); + } +} + +// Return a cookie from the array with the same name, domain, and path as the +// given cookie, or else return nil if none found. +// +// Both the cookie being tested and all cookies in the storage array should +// be valid (non-nil name, domains, paths). +// +// Note: this should only be called from inside a @synchronized(self) block +- (GTM_NULLABLE NSHTTPCookie *)cookieMatchingCookie:(NSHTTPCookie *)cookie { + GTMSessionCheckSynchronized(self); + + NSString *name = cookie.name; + NSString *domain = cookie.domain; + NSString *path = cookie.path; + + GTMSESSION_ASSERT_DEBUG(name && domain && path, + @"Invalid stored cookie (name:%@ domain:%@ path:%@)", name, domain, path); + + for (NSHTTPCookie *storedCookie in _cookies) { + if ([storedCookie.name isEqual:name] + && [storedCookie.domain isEqual:domain] + && [storedCookie.path isEqual:path]) { + return storedCookie; + } + } + return nil; +} + +// Internal routine to remove any expired cookies from the array, excluding +// cookies with nil expirations. +// +// Note: this should only be called from inside a @synchronized(self) block +- (void)removeExpiredCookies { + GTMSessionCheckSynchronized(self); + + // Count backwards since we're deleting items from the array + for (NSInteger idx = (NSInteger)_cookies.count - 1; idx >= 0; idx--) { + NSHTTPCookie *storedCookie = [_cookies objectAtIndex:(NSUInteger)idx]; + if ([[self class] hasCookieExpired:storedCookie]) { + [_cookies removeObjectAtIndex:(NSUInteger)idx]; + } + } +} + ++ (BOOL)hasCookieExpired:(NSHTTPCookie *)cookie { + NSDate *expiresDate = [cookie expiresDate]; + if (expiresDate == nil) { + // Cookies seem to have a Expires property even when the expiresDate method returns nil. + id expiresVal = [[cookie properties] objectForKey:NSHTTPCookieExpires]; + if ([expiresVal isKindOfClass:[NSDate class]]) { + expiresDate = expiresVal; + } + } + BOOL hasExpired = (expiresDate != nil && [expiresDate timeIntervalSinceNow] < 0); + return hasExpired; +} + +- (void)removeAllCookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_cookies removeAllObjects]; + } // @synchronized(self) +} + +- (NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _policy; + } // @synchronized(self) +} + +- (void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _policy = cookieAcceptPolicy; + } // @synchronized(self) +} + +@end + +void GTMSessionFetcherAssertValidSelector(id GTM_NULLABLE_TYPE obj, SEL GTM_NULLABLE_TYPE sel, ...) { + // Verify that the object's selector is implemented with the proper + // number and type of arguments +#if DEBUG + va_list argList; + va_start(argList, sel); + + if (obj && sel) { + // Check that the selector is implemented + if (![obj respondsToSelector:sel]) { + NSLog(@"\"%@\" selector \"%@\" is unimplemented or misnamed", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel)); + NSCAssert(0, @"callback selector unimplemented or misnamed"); + } else { + const char *expectedArgType; + unsigned int argCount = 2; // skip self and _cmd + NSMethodSignature *sig = [obj methodSignatureForSelector:sel]; + + // Check that each expected argument is present and of the correct type + while ((expectedArgType = va_arg(argList, const char*)) != 0) { + + if ([sig numberOfArguments] > argCount) { + const char *foundArgType = [sig getArgumentTypeAtIndex:argCount]; + + if (0 != strncmp(foundArgType, expectedArgType, strlen(expectedArgType))) { + NSLog(@"\"%@\" selector \"%@\" argument %d should be type %s", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel), (argCount - 2), expectedArgType); + NSCAssert(0, @"callback selector argument type mistake"); + } + } + argCount++; + } + + // Check that the proper number of arguments are present in the selector + if (argCount != [sig numberOfArguments]) { + NSLog(@"\"%@\" selector \"%@\" should have %d arguments", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel), (argCount - 2)); + NSCAssert(0, @"callback selector arguments incorrect"); + } + } + } + + va_end(argList); +#endif +} + +NSString *GTMFetcherCleanedUserAgentString(NSString *str) { + // Reference http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html + // and http://www-archive.mozilla.org/build/user-agent-strings.html + + if (str == nil) return @""; + + NSMutableString *result = [NSMutableString stringWithString:str]; + + // Replace spaces and commas with underscores + [result replaceOccurrencesOfString:@" " + withString:@"_" + options:0 + range:NSMakeRange(0, result.length)]; + [result replaceOccurrencesOfString:@"," + withString:@"_" + options:0 + range:NSMakeRange(0, result.length)]; + + // Delete http token separators and remaining whitespace + static NSCharacterSet *charsToDelete = nil; + if (charsToDelete == nil) { + // Make a set of unwanted characters + NSString *const kSeparators = @"()<>@;:\\\"/[]?={}"; + + NSMutableCharacterSet *mutableChars = + [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy]; + [mutableChars addCharactersInString:kSeparators]; + charsToDelete = [mutableChars copy]; // hang on to an immutable copy + } + + while (1) { + NSRange separatorRange = [result rangeOfCharacterFromSet:charsToDelete]; + if (separatorRange.location == NSNotFound) break; + + [result deleteCharactersInRange:separatorRange]; + }; + + return result; +} + +NSString *GTMFetcherSystemVersionString(void) { + static NSString *sSavedSystemString; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The Xcode 8 SDKs finally cleaned up this mess by providing TARGET_OS_OSX + // and TARGET_OS_IOS, but to build with older SDKs, those don't exist and + // instead one has to rely on TARGET_OS_MAC (which is true for iOS, watchOS, + // and tvOS) and TARGET_OS_IPHONE (which is true for iOS, watchOS, tvOS). So + // one has to order these carefully so you pick off the specific things + // first. + // If the code can ever assume Xcode 8 or higher (even when building for + // older OSes), then + // TARGET_OS_MAC -> TARGET_OS_OSX + // TARGET_OS_IPHONE -> TARGET_OS_IOS + // TARGET_IPHONE_SIMULATOR -> TARGET_OS_SIMULATOR +#if TARGET_OS_WATCH + // watchOS - WKInterfaceDevice + + WKInterfaceDevice *currentDevice = [WKInterfaceDevice currentDevice]; + + NSString *rawModel = [currentDevice model]; + NSString *model = GTMFetcherCleanedUserAgentString(rawModel); + + NSString *systemVersion = [currentDevice systemVersion]; + +#if TARGET_OS_SIMULATOR + NSString *hardwareModel = @"sim"; +#else + NSString *hardwareModel; + struct utsname unameRecord; + if (uname(&unameRecord) == 0) { + NSString *machineName = @(unameRecord.machine); + hardwareModel = GTMFetcherCleanedUserAgentString(machineName); + } + if (hardwareModel.length == 0) { + hardwareModel = @"unk"; + } +#endif + + sSavedSystemString = [[NSString alloc] initWithFormat:@"%@/%@ hw/%@", + model, systemVersion, hardwareModel]; + // Example: Apple_Watch/3.0 hw/Watch1_2 +#elif TARGET_OS_TV || TARGET_OS_IPHONE + // iOS and tvOS have UIDevice, use that. + UIDevice *currentDevice = [UIDevice currentDevice]; + + NSString *rawModel = [currentDevice model]; + NSString *model = GTMFetcherCleanedUserAgentString(rawModel); + + NSString *systemVersion = [currentDevice systemVersion]; + +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR + NSString *hardwareModel = @"sim"; +#else + NSString *hardwareModel; + struct utsname unameRecord; + if (uname(&unameRecord) == 0) { + NSString *machineName = @(unameRecord.machine); + hardwareModel = GTMFetcherCleanedUserAgentString(machineName); + } + if (hardwareModel.length == 0) { + hardwareModel = @"unk"; + } +#endif + + sSavedSystemString = [[NSString alloc] initWithFormat:@"%@/%@ hw/%@", + model, systemVersion, hardwareModel]; + // Example: iPod_Touch/2.2 hw/iPod1_1 + // Example: Apple_TV/9.2 hw/AppleTV5,3 +#elif TARGET_OS_MAC + // Mac build + NSProcessInfo *procInfo = [NSProcessInfo processInfo]; +#if !defined(MAC_OS_X_VERSION_10_10) + BOOL hasOperatingSystemVersion = NO; +#elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 + BOOL hasOperatingSystemVersion = + [procInfo respondsToSelector:@selector(operatingSystemVersion)]; +#else + BOOL hasOperatingSystemVersion = YES; +#endif + NSString *versString; + if (hasOperatingSystemVersion) { +#if defined(MAC_OS_X_VERSION_10_10) + // A reference to NSOperatingSystemVersion requires the 10.10 SDK. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +// Disable unguarded availability warning as we can't use the @availability macro until we require +// all clients to build with Xcode 9 or above. + NSOperatingSystemVersion version = procInfo.operatingSystemVersion; +#pragma clang diagnostic pop + versString = [NSString stringWithFormat:@"%ld.%ld.%ld", + (long)version.majorVersion, (long)version.minorVersion, + (long)version.patchVersion]; +#else +#pragma unused(procInfo) +#endif + } else { + // With Gestalt inexplicably deprecated in 10.8, we're reduced to reading + // the system plist file. + NSString *const kPath = @"/System/Library/CoreServices/SystemVersion.plist"; + NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:kPath]; + versString = [plist objectForKey:@"ProductVersion"]; + if (versString.length == 0) { + versString = @"10.?.?"; + } + } + + sSavedSystemString = [[NSString alloc] initWithFormat:@"MacOSX/%@", versString]; +#elif defined(_SYS_UTSNAME_H) + // Foundation-only build + struct utsname unameRecord; + uname(&unameRecord); + + sSavedSystemString = [NSString stringWithFormat:@"%s/%s", + unameRecord.sysname, unameRecord.release]; // "Darwin/8.11.1" +#else +#error No branch taken for a default user agent +#endif + }); + return sSavedSystemString; +} + +NSString *GTMFetcherStandardUserAgentString(NSBundle * GTM_NULLABLE_TYPE bundle) { + NSString *result = [NSString stringWithFormat:@"%@ %@", + GTMFetcherApplicationIdentifier(bundle), + GTMFetcherSystemVersionString()]; + return result; +} + +NSString *GTMFetcherApplicationIdentifier(NSBundle * GTM_NULLABLE_TYPE bundle) { + @synchronized([GTMSessionFetcher class]) { + static NSMutableDictionary *sAppIDMap = nil; + + // If there's a bundle ID, use that; otherwise, use the process name + if (bundle == nil) { + bundle = [NSBundle mainBundle]; + } + NSString *bundleID = [bundle bundleIdentifier]; + if (bundleID == nil) { + bundleID = @""; + } + + NSString *identifier = [sAppIDMap objectForKey:bundleID]; + if (identifier) return identifier; + + // Apps may add a string to the info.plist to uniquely identify different builds. + identifier = [bundle objectForInfoDictionaryKey:@"GTMUserAgentID"]; + if (identifier.length == 0) { + if (bundleID.length > 0) { + identifier = bundleID; + } else { + // Fall back on the procname, prefixed by "proc" to flag that it's + // autogenerated and perhaps unreliable + NSString *procName = [[NSProcessInfo processInfo] processName]; + identifier = [NSString stringWithFormat:@"proc_%@", procName]; + } + } + + // Clean up whitespace and special characters + identifier = GTMFetcherCleanedUserAgentString(identifier); + + // If there's a version number, append that + NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + if (version.length == 0) { + version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + } + + // Clean up whitespace and special characters + version = GTMFetcherCleanedUserAgentString(version); + + // Glue the two together (cleanup done above or else cleanup would strip the + // slash) + if (version.length > 0) { + identifier = [identifier stringByAppendingFormat:@"/%@", version]; + } + + if (sAppIDMap == nil) { + sAppIDMap = [[NSMutableDictionary alloc] init]; + } + [sAppIDMap setObject:identifier forKey:bundleID]; + return identifier; + } +} + +#if DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) +@implementation GTMSessionSyncMonitorInternal { + NSValue *_objectKey; // The synchronize target object. + const char *_functionName; // The function containing the monitored sync block. +} + +- (instancetype)initWithSynchronizationObject:(id)object + allowRecursive:(BOOL)allowRecursive + functionName:(const char *)functionName { + self = [super init]; + if (self) { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + _objectKey = [NSValue valueWithNonretainedObject:object]; + _functionName = functionName; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + if (counters == nil) { + counters = [NSMutableDictionary dictionary]; + threadDict[(id)threadKey] = counters; + } + NSCountedSet *functionNamesCounter = counters[_objectKey]; + NSUInteger numberOfSyncingFunctions = functionNamesCounter.count; + + if (!allowRecursive) { + BOOL isTopLevelSyncScope = (numberOfSyncingFunctions == 0); + NSArray *stack = [NSThread callStackSymbols]; + GTMSESSION_ASSERT_DEBUG(isTopLevelSyncScope, + @"*** Recursive sync on %@ at %s; previous sync at %@\n%@", + [object class], functionName, functionNamesCounter.allObjects, + [stack subarrayWithRange:NSMakeRange(1, stack.count - 1)]); + } + + if (!functionNamesCounter) { + functionNamesCounter = [NSCountedSet set]; + counters[_objectKey] = functionNamesCounter; + } + [functionNamesCounter addObject:(id _Nonnull)@(functionName)]; + } + return self; +} + +- (void)dealloc { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + NSCountedSet *functionNamesCounter = counters[_objectKey]; + NSString *functionNameStr = @(_functionName); + NSUInteger numberOfSyncsByThisFunction = [functionNamesCounter countForObject:functionNameStr]; + NSArray *stack = [NSThread callStackSymbols]; + GTMSESSION_ASSERT_DEBUG(numberOfSyncsByThisFunction > 0, @"Sync not found on %@ at %s\n%@", + [_objectKey.nonretainedObjectValue class], _functionName, + [stack subarrayWithRange:NSMakeRange(1, stack.count - 1)]); + [functionNamesCounter removeObject:functionNameStr]; + if (functionNamesCounter.count == 0) { + [counters removeObjectForKey:_objectKey]; + } +} + ++ (NSArray *)functionsHoldingSynchronizationOnObject:(id)object { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + NSValue *localObjectKey = [NSValue valueWithNonretainedObject:object]; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + NSCountedSet *functionNamesCounter = counters[localObjectKey]; + return functionNamesCounter.count > 0 ? functionNamesCounter.allObjects : nil; +} +@end +#endif // DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) +GTM_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h new file mode 100644 index 00000000..5ccea78e --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h @@ -0,0 +1,112 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTMSessionFetcher.h" + +// GTM HTTP Logging +// +// All traffic using GTMSessionFetcher can be easily logged. Call +// +// [GTMSessionFetcher setLoggingEnabled:YES]; +// +// to begin generating log files. +// +// Unless explicitly set by the application using +setLoggingDirectory:, +// logs are put into a default directory, located at: +// * macOS: ~/Desktop/GTMHTTPDebugLogs +// * iOS simulator: ~/GTMHTTPDebugLogs (in application sandbox) +// * iOS device: ~/Documents/GTMHTTPDebugLogs (in application sandbox) +// +// Tip: use the Finder's "Sort By Date" to find the most recent logs. +// +// Each run of an application gets a separate set of log files. An html +// file is generated to simplify browsing the run's http transactions. +// The html file includes javascript links for inline viewing of uploaded +// and downloaded data. +// +// A symlink is created in the logs folder to simplify finding the html file +// for the latest run of the application; the symlink is called +// +// AppName_http_log_newest.html +// +// For better viewing of XML logs, use Camino or Firefox rather than Safari. +// +// Each fetcher may be given a comment to be inserted as a label in the logs, +// such as +// [fetcher setCommentWithFormat:@"retrieve item %@", itemName]; +// +// Projects may define STRIP_GTM_FETCH_LOGGING to remove logging code. + +#if !STRIP_GTM_FETCH_LOGGING + +@interface GTMSessionFetcher (GTMSessionFetcherLogging) + +// Note: on macOS the default logs directory is ~/Desktop/GTMHTTPDebugLogs; on +// iOS simulators it will be the ~/GTMHTTPDebugLogs (in the app sandbox); on +// iOS devices it will be in ~/Documents/GTMHTTPDebugLogs (in the app sandbox). +// These directories will be created as needed, and are excluded from backups +// to iCloud and iTunes. +// +// If a custom directory is set, the directory should already exist. It is +// the application's responsibility to exclude any custom directory from +// backups, if desired. ++ (void)setLoggingDirectory:(NSString *)path; ++ (NSString *)loggingDirectory; + +// client apps can turn logging on and off ++ (void)setLoggingEnabled:(BOOL)isLoggingEnabled; ++ (BOOL)isLoggingEnabled; + +// client apps can turn off logging to a file if they want to only check +// the fetcher's log property ++ (void)setLoggingToFileEnabled:(BOOL)isLoggingToFileEnabled; ++ (BOOL)isLoggingToFileEnabled; + +// client apps can optionally specify process name and date string used in +// log file names ++ (void)setLoggingProcessName:(NSString *)processName; ++ (NSString *)loggingProcessName; + ++ (void)setLoggingDateStamp:(NSString *)dateStamp; ++ (NSString *)loggingDateStamp; + +// client apps can specify the directory for the log for this specific run, +// typically to match the directory used by another fetcher class, like: +// +// [GTMSessionFetcher setLogDirectoryForCurrentRun:[GTMHTTPFetcher logDirectoryForCurrentRun]]; +// +// Setting this overrides the logging directory, process name, and date stamp when writing +// the log file. ++ (void)setLogDirectoryForCurrentRun:(NSString *)logDirectoryForCurrentRun; ++ (NSString *)logDirectoryForCurrentRun; + +// Prunes old log directories that have not been modified since the provided date. +// This will not delete the current run's log directory. ++ (void)deleteLogDirectoriesOlderThanDate:(NSDate *)date; + +// internal; called by fetcher +- (void)logFetchWithError:(NSError *)error; +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream; +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider; + +// internal; accessors useful for viewing logs ++ (NSString *)processNameLogPrefix; ++ (NSString *)symlinkNameSuffix; ++ (NSString *)htmlFileName; + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m new file mode 100644 index 00000000..cdf5c179 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m @@ -0,0 +1,982 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#include +#include + +#import "GTMSessionFetcherLogging.h" + +#ifndef STRIP_GTM_FETCH_LOGGING + #error GTMSessionFetcher headers should have defaulted this if it wasn't already defined. +#endif + +#if !STRIP_GTM_FETCH_LOGGING + +// Sensitive credential strings are replaced in logs with _snip_ +// +// Apps that must see the contents of sensitive tokens can set this to 1 +#ifndef SKIP_GTM_FETCH_LOGGING_SNIPPING +#define SKIP_GTM_FETCH_LOGGING_SNIPPING 0 +#endif + +// If GTMReadMonitorInputStream is available, it can be used for +// capturing uploaded streams of data +// +// We locally declare methods of GTMReadMonitorInputStream so we +// do not need to import the header, as some projects may not have it available +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMReadMonitorInputStream : NSInputStream + ++ (instancetype)inputStreamWithStream:(NSInputStream *)input; + +@property (assign) id readDelegate; +@property (assign) SEL readSelector; + +@end +#else +@class GTMReadMonitorInputStream; +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionFetcher (GTMHTTPFetcherLoggingUtilities) + ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict; ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr; +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(int64_t)length; + +@end + +@implementation GTMSessionFetcher (GTMSessionFetcherLogging) + +// fetchers come and fetchers go, but statics are forever +static BOOL gIsLoggingEnabled = NO; +static BOOL gIsLoggingToFile = YES; +static NSString *gLoggingDirectoryPath = nil; +static NSString *gLogDirectoryForCurrentRun = nil; +static NSString *gLoggingDateStamp = nil; +static NSString *gLoggingProcessName = nil; + ++ (void)setLoggingDirectory:(NSString *)path { + gLoggingDirectoryPath = [path copy]; +} + ++ (NSString *)loggingDirectory { + if (!gLoggingDirectoryPath) { + NSArray *paths = nil; +#if TARGET_IPHONE_SIMULATOR + // default to a directory called GTMHTTPDebugLogs into a sandbox-safe + // directory that a developer can find easily, the application home + paths = @[ NSHomeDirectory() ]; +#elif TARGET_OS_IPHONE + // Neither ~/Desktop nor ~/Home is writable on an actual iOS, watchOS, or tvOS device. + // Put it in ~/Documents. + paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); +#else + // default to a directory called GTMHTTPDebugLogs in the desktop folder + paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES); +#endif + + NSString *desktopPath = paths.firstObject; + if (desktopPath) { + NSString *const kGTMLogFolderName = @"GTMHTTPDebugLogs"; + NSString *logsFolderPath = [desktopPath stringByAppendingPathComponent:kGTMLogFolderName]; + + NSFileManager *fileMgr = [NSFileManager defaultManager]; + BOOL isDir; + BOOL doesFolderExist = [fileMgr fileExistsAtPath:logsFolderPath isDirectory:&isDir]; + if (!doesFolderExist) { + // make the directory + doesFolderExist = [fileMgr createDirectoryAtPath:logsFolderPath + withIntermediateDirectories:YES + attributes:nil + error:NULL]; + if (doesFolderExist) { + // The directory has been created. Exclude it from backups. + NSURL *pathURL = [NSURL fileURLWithPath:logsFolderPath isDirectory:YES]; + [pathURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:NULL]; + } + } + + if (doesFolderExist) { + // it's there; store it in the global + gLoggingDirectoryPath = [logsFolderPath copy]; + } + } + } + return gLoggingDirectoryPath; +} + ++ (void)setLogDirectoryForCurrentRun:(NSString *)logDirectoryForCurrentRun { + // Set the path for this run's logs. + gLogDirectoryForCurrentRun = [logDirectoryForCurrentRun copy]; +} + ++ (NSString *)logDirectoryForCurrentRun { + // make a directory for this run's logs, like SyncProto_logs_10-16_01-56-58PM + if (gLogDirectoryForCurrentRun) return gLogDirectoryForCurrentRun; + + NSString *parentDir = [self loggingDirectory]; + NSString *logNamePrefix = [self processNameLogPrefix]; + NSString *dateStamp = [self loggingDateStamp]; + NSString *dirName = [NSString stringWithFormat:@"%@%@", logNamePrefix, dateStamp]; + NSString *logDirectory = [parentDir stringByAppendingPathComponent:dirName]; + + if (gIsLoggingToFile) { + NSFileManager *fileMgr = [NSFileManager defaultManager]; + // Be sure that the first time this app runs, it's not writing to a preexisting folder + static BOOL gShouldReuseFolder = NO; + if (!gShouldReuseFolder) { + gShouldReuseFolder = YES; + NSString *origLogDir = logDirectory; + for (int ctr = 2; ctr < 20; ++ctr) { + if (![fileMgr fileExistsAtPath:logDirectory]) break; + + // append a digit + logDirectory = [origLogDir stringByAppendingFormat:@"_%d", ctr]; + } + } + if (![fileMgr createDirectoryAtPath:logDirectory + withIntermediateDirectories:YES + attributes:nil + error:NULL]) return nil; + } + gLogDirectoryForCurrentRun = logDirectory; + + return gLogDirectoryForCurrentRun; +} + ++ (void)setLoggingEnabled:(BOOL)isLoggingEnabled { + gIsLoggingEnabled = isLoggingEnabled; +} + ++ (BOOL)isLoggingEnabled { + return gIsLoggingEnabled; +} + ++ (void)setLoggingToFileEnabled:(BOOL)isLoggingToFileEnabled { + gIsLoggingToFile = isLoggingToFileEnabled; +} + ++ (BOOL)isLoggingToFileEnabled { + return gIsLoggingToFile; +} + ++ (void)setLoggingProcessName:(NSString *)processName { + gLoggingProcessName = [processName copy]; +} + ++ (NSString *)loggingProcessName { + // get the process name (once per run) replacing spaces with underscores + if (!gLoggingProcessName) { + NSString *procName = [[NSProcessInfo processInfo] processName]; + gLoggingProcessName = [procName stringByReplacingOccurrencesOfString:@" " withString:@"_"]; + } + return gLoggingProcessName; +} + ++ (void)setLoggingDateStamp:(NSString *)dateStamp { + gLoggingDateStamp = [dateStamp copy]; +} + ++ (NSString *)loggingDateStamp { + // We'll pick one date stamp per run, so a run that starts at a later second + // will get a unique results html file + if (!gLoggingDateStamp) { + // produce a string like 08-21_01-41-23PM + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setFormatterBehavior:NSDateFormatterBehavior10_4]; + [formatter setDateFormat:@"M-dd_hh-mm-ssa"]; + + gLoggingDateStamp = [formatter stringFromDate:[NSDate date]]; + } + return gLoggingDateStamp; +} + ++ (NSString *)processNameLogPrefix { + static NSString *gPrefix = nil; + if (!gPrefix) { + NSString *processName = [self loggingProcessName]; + gPrefix = [[NSString alloc] initWithFormat:@"%@_log_", processName]; + } + return gPrefix; +} + ++ (NSString *)symlinkNameSuffix { + return @"_log_newest.html"; +} + ++ (NSString *)htmlFileName { + return @"aperçu_http_log.html"; +} + ++ (void)deleteLogDirectoriesOlderThanDate:(NSDate *)cutoffDate { + NSFileManager *fileMgr = [NSFileManager defaultManager]; + NSURL *parentDir = [NSURL fileURLWithPath:[[self class] loggingDirectory]]; + NSURL *logDirectoryForCurrentRun = + [NSURL fileURLWithPath:[[self class] logDirectoryForCurrentRun]]; + NSError *error; + NSArray *contents = [fileMgr contentsOfDirectoryAtURL:parentDir + includingPropertiesForKeys:@[ NSURLContentModificationDateKey ] + options:0 + error:&error]; + for (NSURL *itemURL in contents) { + if ([itemURL isEqual:logDirectoryForCurrentRun]) continue; + + NSDate *modDate; + if ([itemURL getResourceValue:&modDate + forKey:NSURLContentModificationDateKey + error:&error]) { + if ([modDate compare:cutoffDate] == NSOrderedAscending) { + if (![fileMgr removeItemAtURL:itemURL error:&error]) { + NSLog(@"deleteLogDirectoriesOlderThanDate failed to delete %@: %@", + itemURL.path, error); + } + } + } else { + NSLog(@"deleteLogDirectoriesOlderThanDate failed to get mod date of %@: %@", + itemURL.path, error); + } + } +} + +// formattedStringFromData returns a prettyprinted string for XML or JSON input, +// and a plain string for other input data +- (NSString *)formattedStringFromData:(NSData *)inputData + contentType:(NSString *)contentType + JSON:(NSDictionary **)outJSON { + if (!inputData) return nil; + + // if the content type is JSON and we have the parsing class available, use that + if ([contentType hasPrefix:@"application/json"] && inputData.length > 5) { + // convert from JSON string to NSObjects and back to a formatted string + NSMutableDictionary *obj = [NSJSONSerialization JSONObjectWithData:inputData + options:NSJSONReadingMutableContainers + error:NULL]; + if (obj) { + if (outJSON) *outJSON = obj; + if ([obj isKindOfClass:[NSMutableDictionary class]]) { + // for security and privacy, omit OAuth 2 response access and refresh tokens + if ([obj valueForKey:@"refresh_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"refresh_token"]; + } + if ([obj valueForKey:@"access_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"access_token"]; + } + } + NSData *data = [NSJSONSerialization dataWithJSONObject:obj + options:NSJSONWritingPrettyPrinted + error:NULL]; + if (data) { + NSString *jsonStr = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + return jsonStr; + } + } + } + +#if !TARGET_OS_IPHONE && !GTM_SKIP_LOG_XMLFORMAT + // verify that this data starts with the bytes indicating XML + + NSString *const kXMLLintPath = @"/usr/bin/xmllint"; + static BOOL gHasCheckedAvailability = NO; + static BOOL gIsXMLLintAvailable = NO; + + if (!gHasCheckedAvailability) { + gIsXMLLintAvailable = [[NSFileManager defaultManager] fileExistsAtPath:kXMLLintPath]; + gHasCheckedAvailability = YES; + } + if (gIsXMLLintAvailable + && inputData.length > 5 + && strncmp(inputData.bytes, " 0) { + // success + inputData = formattedData; + } + } +#else + // we can't call external tasks on the iPhone; leave the XML unformatted +#endif + + NSString *dataStr = [[NSString alloc] initWithData:inputData + encoding:NSUTF8StringEncoding]; + return dataStr; +} + +// stringFromStreamData creates a string given the supplied data +// +// If NSString can create a UTF-8 string from the data, then that is returned. +// +// Otherwise, this routine tries to find a MIME boundary at the beginning of the data block, and +// uses that to break up the data into parts. Each part will be used to try to make a UTF-8 string. +// For parts that fail, a replacement string showing the part header and <> is supplied +// in place of the binary data. + +- (NSString *)stringFromStreamData:(NSData *)data + contentType:(NSString *)contentType { + + if (!data) return nil; + + // optimistically, see if the whole data block is UTF-8 + NSString *streamDataStr = [self formattedStringFromData:data + contentType:contentType + JSON:NULL]; + if (streamDataStr) return streamDataStr; + + // Munge a buffer by replacing non-ASCII bytes with underscores, and turn that munged buffer an + // NSString. That gives us a string we can use with NSScanner. + NSMutableData *mutableData = [NSMutableData dataWithData:data]; + unsigned char *bytes = (unsigned char *)mutableData.mutableBytes; + + for (unsigned int idx = 0; idx < mutableData.length; ++idx) { + if (bytes[idx] > 0x7F || bytes[idx] == 0) { + bytes[idx] = '_'; + } + } + + NSString *mungedStr = [[NSString alloc] initWithData:mutableData + encoding:NSUTF8StringEncoding]; + if (mungedStr) { + + // scan for the boundary string + NSString *boundary = nil; + NSScanner *scanner = [NSScanner scannerWithString:mungedStr]; + + if ([scanner scanUpToString:@"\r\n" intoString:&boundary] + && [boundary hasPrefix:@"--"]) { + + // we found a boundary string; use it to divide the string into parts + NSArray *mungedParts = [mungedStr componentsSeparatedByString:boundary]; + + // look at each munged part in the original string, and try to convert those into UTF-8 + NSMutableArray *origParts = [NSMutableArray array]; + NSUInteger offset = 0; + for (NSString *mungedPart in mungedParts) { + NSUInteger partSize = mungedPart.length; + NSData *origPartData = [data subdataWithRange:NSMakeRange(offset, partSize)]; + NSString *origPartStr = [[NSString alloc] initWithData:origPartData + encoding:NSUTF8StringEncoding]; + if (origPartStr) { + // we could make this original part into UTF-8; use the string + [origParts addObject:origPartStr]; + } else { + // this part can't be made into UTF-8; scan the header, if we can + NSString *header = nil; + NSScanner *headerScanner = [NSScanner scannerWithString:mungedPart]; + if (![headerScanner scanUpToString:@"\r\n\r\n" intoString:&header]) { + // we couldn't find a header + header = @""; + } + // make a part string with the header and <> + NSString *binStr = [NSString stringWithFormat:@"\r%@\r<<%lu bytes>>\r", + header, (long)(partSize - header.length)]; + [origParts addObject:binStr]; + } + offset += partSize + boundary.length; + } + // rejoin the original parts + streamDataStr = [origParts componentsJoinedByString:boundary]; + } + } + if (!streamDataStr) { + // give up; just make a string showing the uploaded bytes + streamDataStr = [NSString stringWithFormat:@"<<%u bytes>>", (unsigned int)data.length]; + } + return streamDataStr; +} + +// logFetchWithError is called following a successful or failed fetch attempt +// +// This method does all the work for appending to and creating log files + +- (void)logFetchWithError:(NSError *)error { + if (![[self class] isLoggingEnabled]) return; + NSString *logDirectory = [[self class] logDirectoryForCurrentRun]; + if (!logDirectory) return; + NSString *processName = [[self class] loggingProcessName]; + + // TODO: add Javascript to display response data formatted in hex + + // each response's NSData goes into its own xml or txt file, though all responses for this run of + // the app share a main html file. This counter tracks all fetch responses for this app run. + // + // we'll use a local variable since this routine may be reentered while waiting for XML formatting + // to be completed by an external task + static int gResponseCounter = 0; + int responseCounter = ++gResponseCounter; + + NSURLResponse *response = [self response]; + NSDictionary *responseHeaders = [self responseHeaders]; + NSString *responseDataStr = nil; + NSDictionary *responseJSON = nil; + + // if there's response data, decide what kind of file to put it in based on the first bytes of the + // file or on the mime type supplied by the server + NSString *responseMIMEType = [response MIMEType]; + BOOL isResponseImage = NO; + + // file name for an image data file + NSString *responseDataFileName = nil; + + int64_t responseDataLength = self.downloadedLength; + if (responseDataLength > 0) { + NSData *downloadedData = self.downloadedData; + if (downloadedData == nil + && responseDataLength > 0 + && responseDataLength < 20000 + && self.destinationFileURL) { + // There's a download file that's not too big, so get the data to display from the downloaded + // file. + NSURL *destinationURL = self.destinationFileURL; + downloadedData = [NSData dataWithContentsOfURL:destinationURL]; + } + NSString *responseType = [responseHeaders valueForKey:@"Content-Type"]; + responseDataStr = [self formattedStringFromData:downloadedData + contentType:responseType + JSON:&responseJSON]; + NSString *responseDataExtn = nil; + NSData *dataToWrite = nil; + if (responseDataStr) { + // we were able to make a UTF-8 string from the response data + if ([responseMIMEType isEqual:@"application/atom+xml"] + || [responseMIMEType hasSuffix:@"/xml"]) { + responseDataExtn = @"xml"; + dataToWrite = [responseDataStr dataUsingEncoding:NSUTF8StringEncoding]; + } + } else if ([responseMIMEType isEqual:@"image/jpeg"]) { + responseDataExtn = @"jpg"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/gif"]) { + responseDataExtn = @"gif"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/png"]) { + responseDataExtn = @"png"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else { + // add more non-text types here + } + // if we have an extension, save the raw data in a file with that extension + if (responseDataExtn && dataToWrite) { + // generate a response file base name like + NSString *responseBaseName = [NSString stringWithFormat:@"fetch_%d_response", responseCounter]; + responseDataFileName = [responseBaseName stringByAppendingPathExtension:responseDataExtn]; + NSString *responseDataFilePath = [logDirectory stringByAppendingPathComponent:responseDataFileName]; + + NSError *downloadedError = nil; + if (gIsLoggingToFile && ![dataToWrite writeToFile:responseDataFilePath + options:0 + error:&downloadedError]) { + NSLog(@"%@ logging write error:%@ (%@)", [self class], downloadedError, responseDataFileName); + } + } + } + // we'll have one main html file per run of the app + NSString *htmlName = [[self class] htmlFileName]; + NSString *htmlPath =[logDirectory stringByAppendingPathComponent:htmlName]; + + // if the html file exists (from logging previous fetches) we don't need + // to re-write the header or the scripts + NSFileManager *fileMgr = [NSFileManager defaultManager]; + BOOL didFileExist = [fileMgr fileExistsAtPath:htmlPath]; + + NSMutableString* outputHTML = [NSMutableString string]; + + // we need a header to say we'll have UTF-8 text + if (!didFileExist) { + [outputHTML appendFormat:@"%@ HTTP fetch log %@", + processName, [[self class] loggingDateStamp]]; + } + // now write the visible html elements + NSString *copyableFileName = [NSString stringWithFormat:@"fetch_%d.txt", responseCounter]; + + NSDate *now = [NSDate date]; + // write the date & time, the comment, and the link to the plain-text (copyable) log + [outputHTML appendFormat:@"%@      ", now]; + + NSString *comment = [self comment]; + if (comment.length > 0) { + [outputHTML appendFormat:@"%@      ", comment]; + } + [outputHTML appendFormat:@"request/response log
", copyableFileName]; + NSTimeInterval elapsed = -self.initialBeginFetchDate.timeIntervalSinceNow; + [outputHTML appendFormat:@"elapsed: %5.3fsec
", elapsed]; + + // write the request URL + NSURLRequest *request = self.request; + NSString *requestMethod = request.HTTPMethod; + NSURL *requestURL = request.URL; + + // Save the request URL for next time in case this redirects. + NSString *redirectedFromURLString = [self.redirectedFromURL absoluteString]; + self.redirectedFromURL = [requestURL copy]; + if (redirectedFromURLString) { + [outputHTML appendFormat:@"redirected from %@
", + redirectedFromURLString]; + } + [outputHTML appendFormat:@"request: %@ %@
\n", requestMethod, requestURL]; + + // write the request headers + NSDictionary *requestHeaders = request.allHTTPHeaderFields; + NSUInteger numberOfRequestHeaders = requestHeaders.count; + if (numberOfRequestHeaders > 0) { + // Indicate if the request is authorized; warn if the request is authorized but non-SSL + NSString *auth = [requestHeaders objectForKey:@"Authorization"]; + NSString *headerDetails = @""; + if (auth) { + BOOL isInsecure = [[requestURL scheme] isEqual:@"http"]; + if (isInsecure) { + // 26A0 = ⚠ + headerDetails = + @"   authorized, non-SSL "; + } else { + headerDetails = @"   authorized"; + } + } + NSString *cookiesHdr = [requestHeaders objectForKey:@"Cookie"]; + if (cookiesHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   cookies"]; + } + NSString *matchHdr = [requestHeaders objectForKey:@"If-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   if-match"]; + } + matchHdr = [requestHeaders objectForKey:@"If-None-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   if-none-match"]; + } + [outputHTML appendFormat:@"   headers: %d %@
", + (int)numberOfRequestHeaders, headerDetails]; + } else { + [outputHTML appendFormat:@"   headers: none
"]; + } + // write the request post data + NSData *bodyData = nil; + NSData *loggedStreamData = self.loggedStreamData; + if (loggedStreamData) { + bodyData = loggedStreamData; + } else { + bodyData = self.bodyData; + if (bodyData == nil) { + bodyData = self.request.HTTPBody; + } + } + uint64_t bodyDataLength = bodyData.length; + + if (bodyData.length == 0) { + // If the data is in a body upload file URL, read that in if it's not huge. + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSNumber *fileSizeNum = nil; + NSError *fileSizeError = nil; + if ([bodyFileURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:&fileSizeError]) { + bodyDataLength = [fileSizeNum unsignedLongLongValue]; + if (bodyDataLength > 0 && bodyDataLength < 50000) { + bodyData = [NSData dataWithContentsOfURL:bodyFileURL + options:NSDataReadingUncached + error:&fileSizeError]; + } + } + } + } + NSString *bodyDataStr = nil; + NSString *postType = [requestHeaders valueForKey:@"Content-Type"]; + + if (bodyDataLength > 0) { + [outputHTML appendFormat:@"   data: %llu bytes, %@
\n", + bodyDataLength, postType ? postType : @"(no type)"]; + NSString *logRequestBody = self.logRequestBody; + if (logRequestBody) { + bodyDataStr = [logRequestBody copy]; + self.logRequestBody = nil; + } else { + bodyDataStr = [self stringFromStreamData:bodyData + contentType:postType]; + if (bodyDataStr) { + // remove OAuth 2 client secret and refresh token + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"client_secret=" + endString:@"&"]; + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"refresh_token=" + endString:@"&"]; + // remove ClientLogin password + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"&Passwd=" + endString:@"&"]; + } + } + } else { + // no post data + } + // write the response status, MIME type, URL + NSInteger status = [self statusCode]; + if (response) { + NSString *statusString = @""; + if (status != 0) { + if (status == 200 || status == 201) { + statusString = [NSString stringWithFormat:@"%ld", (long)status]; + + // report any JSON-RPC error + if ([responseJSON isKindOfClass:[NSDictionary class]]) { + NSDictionary *jsonError = [responseJSON objectForKey:@"error"]; + if ([jsonError isKindOfClass:[NSDictionary class]]) { + NSString *jsonCode = [[jsonError valueForKey:@"code"] description]; + NSString *jsonMessage = [jsonError valueForKey:@"message"]; + if (jsonCode || jsonMessage) { + // 2691 = ⚑ + NSString *const jsonErrFmt = + @"   JSON error: %@ %@  ⚑"; + statusString = [statusString stringByAppendingFormat:jsonErrFmt, + jsonCode ? jsonCode : @"", + jsonMessage ? jsonMessage : @""]; + } + } + } + } else { + // purple for anything other than 200 or 201 + NSString *flag = status >= 400 ? @" ⚑" : @""; // 2691 = ⚑ + NSString *explanation = [NSHTTPURLResponse localizedStringForStatusCode:status]; + NSString *const statusFormat = @"%ld %@ %@"; + statusString = [NSString stringWithFormat:statusFormat, (long)status, explanation, flag]; + } + } + // show the response URL only if it's different from the request URL + NSString *responseURLStr = @""; + NSURL *responseURL = response.URL; + + if (responseURL && ![responseURL isEqual:request.URL]) { + NSString *const responseURLFormat = + @"response URL: %@
\n"; + responseURLStr = [NSString stringWithFormat:responseURLFormat, [responseURL absoluteString]]; + } + [outputHTML appendFormat:@"response:  status %@
\n%@", + statusString, responseURLStr]; + // Write the response headers + NSUInteger numberOfResponseHeaders = responseHeaders.count; + if (numberOfResponseHeaders > 0) { + // Indicate if the server is setting cookies + NSString *cookiesSet = [responseHeaders valueForKey:@"Set-Cookie"]; + NSString *cookiesStr = + cookiesSet ? @"  sets cookies" : @""; + // Indicate if the server is redirecting + NSString *location = [responseHeaders valueForKey:@"Location"]; + BOOL isRedirect = status >= 300 && status <= 399 && location != nil; + NSString *redirectsStr = + isRedirect ? @"  redirects" : @""; + [outputHTML appendFormat:@"   headers: %d %@ %@
\n", + (int)numberOfResponseHeaders, cookiesStr, redirectsStr]; + } else { + [outputHTML appendString:@"   headers: none
\n"]; + } + } + // error + if (error) { + [outputHTML appendFormat:@"Error: %@
\n", error.description]; + } + // Write the response data + if (responseDataFileName) { + if (isResponseImage) { + // Make a small inline image that links to the full image file + [outputHTML appendFormat:@"   data: %lld bytes, %@
", + responseDataLength, responseMIMEType]; + NSString *const fmt = + @"image\n"; + [outputHTML appendFormat:fmt, responseDataFileName, responseDataFileName]; + } else { + // The response data was XML; link to the xml file + NSString *const fmt = + @"   data: %lld bytes, %@   %@\n"; + [outputHTML appendFormat:fmt, responseDataLength, responseMIMEType, + responseDataFileName, [responseDataFileName pathExtension]]; + } + } else { + // The response data was not an image; just show the length and MIME type + [outputHTML appendFormat:@"   data: %lld bytes, %@\n", + responseDataLength, responseMIMEType ? responseMIMEType : @"(no response type)"]; + } + // Make a single string of the request and response, suitable for copying + // to the clipboard and pasting into a bug report + NSMutableString *copyable = [NSMutableString string]; + if (comment) { + [copyable appendFormat:@"%@\n\n", comment]; + } + [copyable appendFormat:@"%@ elapsed: %5.3fsec\n", now, elapsed]; + if (redirectedFromURLString) { + [copyable appendFormat:@"Redirected from %@\n", redirectedFromURLString]; + } + [copyable appendFormat:@"Request: %@ %@\n", requestMethod, requestURL]; + if (requestHeaders.count > 0) { + [copyable appendFormat:@"Request headers:\n%@\n", + [[self class] headersStringForDictionary:requestHeaders]]; + } + if (bodyDataLength > 0) { + [copyable appendFormat:@"Request body: (%llu bytes)\n", bodyDataLength]; + if (bodyDataStr) { + [copyable appendFormat:@"%@\n", bodyDataStr]; + } + [copyable appendString:@"\n"]; + } + if (response) { + [copyable appendFormat:@"Response: status %d\n", (int) status]; + [copyable appendFormat:@"Response headers:\n%@\n", + [[self class] headersStringForDictionary:responseHeaders]]; + [copyable appendFormat:@"Response body: (%lld bytes)\n", responseDataLength]; + if (responseDataLength > 0) { + NSString *logResponseBody = self.logResponseBody; + if (logResponseBody) { + // The user has provided the response body text. + responseDataStr = [logResponseBody copy]; + self.logResponseBody = nil; + } + if (responseDataStr != nil) { + [copyable appendFormat:@"%@\n", responseDataStr]; + } else { + // Even though it's redundant, we'll put in text to indicate that all the bytes are binary. + if (self.destinationFileURL) { + [copyable appendFormat:@"<<%lld bytes>> to file %@\n", + responseDataLength, self.destinationFileURL.path]; + } else { + [copyable appendFormat:@"<<%lld bytes>>\n", responseDataLength]; + } + } + } + } + if (error) { + [copyable appendFormat:@"Error: %@\n", error]; + } + // Save to log property before adding the separator + self.log = copyable; + + [copyable appendString:@"-----------------------------------------------------------\n"]; + + // Write the copyable version to another file (linked to at the top of the html file, above) + // + // Ideally, something to just copy this to the clipboard like + // Copy here." + // would work everywhere, but it only works in Safari as of 8/2010 + if (gIsLoggingToFile) { + NSString *parentDir = [[self class] loggingDirectory]; + NSString *copyablePath = [logDirectory stringByAppendingPathComponent:copyableFileName]; + NSError *copyableError = nil; + if (![copyable writeToFile:copyablePath + atomically:NO + encoding:NSUTF8StringEncoding + error:©ableError]) { + // Error writing to file + NSLog(@"%@ logging write error:%@ (%@)", [self class], copyableError, copyablePath); + } + [outputHTML appendString:@"

"]; + + // Append the HTML to the main output file + const char* htmlBytes = outputHTML.UTF8String; + NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:htmlPath + append:YES]; + [stream open]; + [stream write:(const uint8_t *) htmlBytes maxLength:strlen(htmlBytes)]; + [stream close]; + + // Make a symlink to the latest html + NSString *const symlinkNameSuffix = [[self class] symlinkNameSuffix]; + NSString *symlinkName = [processName stringByAppendingString:symlinkNameSuffix]; + NSString *symlinkPath = [parentDir stringByAppendingPathComponent:symlinkName]; + + [fileMgr removeItemAtPath:symlinkPath error:NULL]; + [fileMgr createSymbolicLinkAtPath:symlinkPath + withDestinationPath:htmlPath + error:NULL]; +#if TARGET_OS_IPHONE + static BOOL gReportedLoggingPath = NO; + if (!gReportedLoggingPath) { + gReportedLoggingPath = YES; + NSLog(@"GTMSessionFetcher logging to \"%@\"", parentDir); + } +#endif + } +} + +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream { + if (!inputStream) return nil; + if (![GTMSessionFetcher isLoggingEnabled]) return inputStream; + + [self clearLoggedStreamData]; // Clear any previous data. + Class monitorClass = NSClassFromString(@"GTMReadMonitorInputStream"); + if (!monitorClass) { + NSString const *str = @"<>"; + NSData *stringData = [str dataUsingEncoding:NSUTF8StringEncoding]; + [self appendLoggedStreamData:stringData]; + return inputStream; + } + inputStream = [monitorClass inputStreamWithStream:inputStream]; + + GTMReadMonitorInputStream *readMonitorInputStream = (GTMReadMonitorInputStream *)inputStream; + [readMonitorInputStream setReadDelegate:self]; + SEL readSel = @selector(inputStream:readIntoBuffer:length:); + [readMonitorInputStream setReadSelector:readSel]; + + return inputStream; +} + +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider { + if (!streamProvider) return nil; + if (![GTMSessionFetcher isLoggingEnabled]) return streamProvider; + + [self clearLoggedStreamData]; // Clear any previous data. + Class monitorClass = NSClassFromString(@"GTMReadMonitorInputStream"); + if (!monitorClass) { + NSString const *str = @"<>"; + NSData *stringData = [str dataUsingEncoding:NSUTF8StringEncoding]; + [self appendLoggedStreamData:stringData]; + return streamProvider; + } + GTMSessionFetcherBodyStreamProvider loggedStreamProvider = + ^(GTMSessionFetcherBodyStreamProviderResponse response) { + streamProvider(^(NSInputStream *bodyStream) { + bodyStream = [self loggedInputStreamForInputStream:bodyStream]; + response(bodyStream); + }); + }; + return loggedStreamProvider; +} + +@end + +@implementation GTMSessionFetcher (GTMSessionFetcherLoggingUtilities) + +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(int64_t)length { + // append the captured data + NSData *data = [NSData dataWithBytesNoCopy:buffer + length:(NSUInteger)length + freeWhenDone:NO]; + [self appendLoggedStreamData:data]; +} + +#pragma mark Fomatting Utilities + ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr { +#if SKIP_GTM_FETCH_LOGGING_SNIPPING + return originalStr; +#else + if (!originalStr) return nil; + + // Find the start string, and replace everything between it + // and the end string (or the end of the original string) with "_snip_" + NSRange startRange = [originalStr rangeOfString:startStr]; + if (startRange.location == NSNotFound) return originalStr; + + // We found the start string + NSUInteger originalLength = originalStr.length; + NSUInteger startOfTarget = NSMaxRange(startRange); + NSRange targetAndRest = NSMakeRange(startOfTarget, originalLength - startOfTarget); + NSRange endRange = [originalStr rangeOfString:endStr + options:0 + range:targetAndRest]; + NSRange replaceRange; + if (endRange.location == NSNotFound) { + // Found no end marker so replace to end of string + replaceRange = targetAndRest; + } else { + // Replace up to the endStr + replaceRange = NSMakeRange(startOfTarget, endRange.location - startOfTarget); + } + NSString *result = [originalStr stringByReplacingCharactersInRange:replaceRange + withString:@"_snip_"]; + return result; +#endif // SKIP_GTM_FETCH_LOGGING_SNIPPING +} + ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict { + // Format the dictionary in http header style, like + // Accept: application/json + // Cache-Control: no-cache + // Content-Type: application/json; charset=utf-8 + // + // Pad the key names, but not beyond 16 chars, since long custom header + // keys just create too much whitespace + NSArray *keys = [dict.allKeys sortedArrayUsingSelector:@selector(compare:)]; + + NSMutableString *str = [NSMutableString string]; + for (NSString *key in keys) { + NSString *value = [dict valueForKey:key]; + if ([key isEqual:@"Authorization"]) { + // Remove OAuth 1 token + value = [[self class] snipSubstringOfString:value + betweenStartString:@"oauth_token=\"" + endString:@"\""]; + + // Remove OAuth 2 bearer token (draft 16, and older form) + value = [[self class] snipSubstringOfString:value + betweenStartString:@"Bearer " + endString:@"\n"]; + value = [[self class] snipSubstringOfString:value + betweenStartString:@"OAuth " + endString:@"\n"]; + + // Remove Google ClientLogin + value = [[self class] snipSubstringOfString:value + betweenStartString:@"GoogleLogin auth=" + endString:@"\n"]; + } + [str appendFormat:@" %@: %@\n", key, value]; + } + return str; +} + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h new file mode 100644 index 00000000..312abaa7 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h @@ -0,0 +1,196 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// For best performance and convenient usage, fetchers should be generated by a common +// GTMSessionFetcherService instance, like +// +// _fetcherService = [[GTMSessionFetcherService alloc] init]; +// GTMSessionFetcher* myFirstFetcher = [_fetcherService fetcherWithRequest:request1]; +// GTMSessionFetcher* mySecondFetcher = [_fetcherService fetcherWithRequest:request2]; + +#import "GTMSessionFetcher.h" + +GTM_ASSUME_NONNULL_BEGIN + +// Notifications. + +// This notification indicates a reusable session has become invalid. It is intended mainly for the +// service's unit tests. +// +// The notification object is the fetcher service. +// The invalid session is provided via the userInfo kGTMSessionFetcherServiceSessionKey key. +extern NSString *const kGTMSessionFetcherServiceSessionBecameInvalidNotification; +extern NSString *const kGTMSessionFetcherServiceSessionKey; + +@interface GTMSessionFetcherService : NSObject + +// Queues of delayed and running fetchers. Each dictionary contains arrays +// of GTMSessionFetcher *fetchers, keyed by NSString *host +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSArray *) *delayedFetchersByHost; +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSArray *) *runningFetchersByHost; + +// A max value of 0 means no fetchers should be delayed. +// The default limit is 10 simultaneous fetchers targeting each host. +// This does not apply to fetchers whose useBackgroundSession property is YES. Since services are +// not resurrected on an app relaunch, delayed fetchers would effectively be abandoned. +@property(atomic, assign) NSUInteger maxRunningFetchersPerHost; + +// Properties to be applied to each fetcher; see GTMSessionFetcher.h for descriptions +@property(atomic, strong, GTM_NULLABLE) NSURLSessionConfiguration *configuration; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherConfigurationBlock configurationBlock; +@property(atomic, strong, GTM_NULLABLE) NSHTTPCookieStorage *cookieStorage; +@property(atomic, strong, GTM_NULL_RESETTABLE) dispatch_queue_t callbackQueue; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherChallengeBlock challengeBlock; +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *credential; +@property(atomic, strong) NSURLCredential *proxyCredential; +@property(atomic, copy, GTM_NULLABLE) GTM_NSArrayOf(NSString *) *allowedInsecureSchemes; +@property(atomic, assign) BOOL allowLocalhostRequest; +@property(atomic, assign) BOOL allowInvalidServerCertificates; +@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherRetryBlock retryBlock; +@property(atomic, assign) NSTimeInterval maxRetryInterval; +@property(atomic, assign) NSTimeInterval minRetryInterval; +@property(atomic, copy, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, id) *properties; +@property(atomic, copy, GTM_NULLABLE) + GTMSessionFetcherMetricsCollectionBlock metricsCollectionBlock API_AVAILABLE( + ios(10.0), macosx(10.12), tvos(10.0), watchos(3.0)); + +#if GTM_BACKGROUND_TASK_FETCHING +@property(atomic, assign) BOOL skipBackgroundTask; +#endif + +// A default useragent of GTMFetcherStandardUserAgentString(nil) will be given to each fetcher +// created by this service unless the request already has a user-agent header set. +// This default will be added starting with builds with the SDKs for OS X 10.11 and iOS 9. +// +// To use the configuration's default user agent, set this property to nil. +@property(atomic, copy, GTM_NULLABLE) NSString *userAgent; + +// The authorizer to attach to the created fetchers. If a specific fetcher should +// not authorize its requests, the fetcher's authorizer property may be set to nil +// before the fetch begins. +@property(atomic, strong, GTM_NULLABLE) id authorizer; + +// Delegate queue used by the session when calling back to the fetcher. The default +// is the main queue. Changing this does not affect the queue used to call back to the +// application; that is specified by the callbackQueue property above. +@property(atomic, strong, GTM_NULL_RESETTABLE) NSOperationQueue *sessionDelegateQueue; + +// When enabled, indicates the same session should be used by subsequent fetchers. +// +// This is enabled by default. +@property(atomic, assign) BOOL reuseSession; + +// Sets the delay until an unused session is invalidated. +// The default interval is 60 seconds. +// +// If the interval is set to 0, then any reused session is not invalidated except by +// explicitly invoking -resetSession. Be aware that setting the interval to 0 thus +// causes the session's delegate to be retained until the session is explicitly reset. +@property(atomic, assign) NSTimeInterval unusedSessionTimeout; + +// If shouldReuseSession is enabled, this will force creation of a new session when future +// fetchers begin. +- (void)resetSession; + +// Create a fetcher +// +// These methods will return a fetcher. If successfully created, the connection +// will hold a strong reference to it for the life of the connection as well. +// So the caller doesn't have to hold onto the fetcher explicitly unless they +// want to be able to monitor or cancel it. +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (GTMSessionFetcher *)fetcherWithURL:(NSURL *)requestURL; +- (GTMSessionFetcher *)fetcherWithURLString:(NSString *)requestURLString; + +// Common method for fetcher creation. +// +// -fetcherWithRequest:fetcherClass: may be overridden to customize creation of +// fetchers. This is the ONLY method in the GTMSessionFetcher library intended to +// be overridden. +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass; + +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher; + +- (NSUInteger)numberOfFetchers; // running + delayed fetchers +- (NSUInteger)numberOfRunningFetchers; +- (NSUInteger)numberOfDelayedFetchers; + +// Return a list of all running or delayed fetchers. This includes fetchers created +// by the service which have been started and have not yet stopped. +// +// Returns an array of fetcher objects, or nil if none. +- (GTM_NULLABLE GTM_NSArrayOf(GTMSessionFetcher *) *)issuedFetchers; + +// Search for running or delayed fetchers with the specified URL. +// +// Returns an array of fetcher objects found, or nil if none found. +- (GTM_NULLABLE GTM_NSArrayOf(GTMSessionFetcher *) *)issuedFetchersWithRequestURL:(NSURL *)requestURL; + +- (void)stopAllFetchers; + +// Methods for use by the fetcher class only. +- (GTM_NULLABLE NSURLSession *)session; +- (GTM_NULLABLE NSURLSession *)sessionForFetcherCreation; +- (GTM_NULLABLE id)sessionDelegate; +- (GTM_NULLABLE NSDate *)stoppedAllFetchersDate; + +// The testBlock can inspect its fetcher parameter's request property to +// determine which fetcher is being faked. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherTestBlock testBlock; + +@end + +@interface GTMSessionFetcherService (TestingSupport) + +// Convenience methods to create a fetcher service for testing. +// +// Fetchers generated by this mock fetcher service will not perform any +// network operation, but will invoke callbacks and provide the supplied data +// or error to the completion handler. +// +// You can make more customized mocks by setting the test block property of the service +// or fetcher; the test block can inspect the fetcher's request or other properties. +// +// See the description of the testBlock property below. ++ (instancetype)mockFetcherServiceWithFakedData:(GTM_NULLABLE NSData *)fakedDataOrNil + fakedError:(GTM_NULLABLE NSError *)fakedErrorOrNil; ++ (instancetype)mockFetcherServiceWithFakedData:(GTM_NULLABLE NSData *)fakedDataOrNil + fakedResponse:(NSHTTPURLResponse *)fakedResponse + fakedError:(GTM_NULLABLE NSError *)fakedErrorOrNil; + +// Spin the run loop and discard events (or, if not on the main thread, just sleep the thread) +// until all running and delayed fetchers have completed. +// +// This is only for use in testing or in tools without a user interface. +// +// Synchronous fetches should never be done by shipping apps; they are +// sufficient reason for rejection from the app store. +// +// Returns NO if timed out. +- (BOOL)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds; + +@end + +@interface GTMSessionFetcherService (BackwardsCompatibilityOnly) + +// Clients using GTMSessionFetcher should set the cookie storage explicitly themselves. +// This method is just for compatibility with the old fetcher. +@property(atomic, assign) NSInteger cookieStorageMethod; + +@end + +GTM_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m new file mode 100644 index 00000000..f9942c01 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m @@ -0,0 +1,1381 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionFetcherService.h" + +NSString *const kGTMSessionFetcherServiceSessionBecameInvalidNotification + = @"kGTMSessionFetcherServiceSessionBecameInvalidNotification"; +NSString *const kGTMSessionFetcherServiceSessionKey + = @"kGTMSessionFetcherServiceSessionKey"; + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (ServiceMethods) +- (BOOL)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize; +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionFetcherService () + +@property(atomic, strong, readwrite) NSDictionary *delayedFetchersByHost; +@property(atomic, strong, readwrite) NSDictionary *runningFetchersByHost; + +@end + +// Since NSURLSession doesn't support a separate delegate per task (!), instances of this +// class serve as a session delegate trampoline. +// +// This class maps a session's tasks to fetchers, and resends delegate messages to the task's +// fetcher. +@interface GTMSessionFetcherSessionDelegateDispatcher : NSObject + +// The session for the tasks in this dispatcher's task-to-fetcher map. +@property(atomic) NSURLSession *session; + +// The timer interval for invalidating a session that has no active tasks. +@property(atomic) NSTimeInterval discardInterval; + +// The current discard timer. +@property(atomic, readonly) NSTimer *discardTimer; + + +- (instancetype)initWithParentService:(GTMSessionFetcherService *)parentService + sessionDiscardInterval:(NSTimeInterval)discardInterval; + +- (void)setFetcher:(GTMSessionFetcher *)fetcher + forTask:(NSURLSessionTask *)task; +- (void)removeFetcher:(GTMSessionFetcher *)fetcher; + +// Before using a session, tells the delegate dispatcher to stop the discard timer. +- (void)startSessionUsage; + +// When abandoning a delegate dispatcher, we want to avoid the session retaining +// the delegate after tasks complete. +- (void)abandon; + +@end + + +@implementation GTMSessionFetcherService { + NSMutableDictionary *_delayedFetchersByHost; + NSMutableDictionary *_runningFetchersByHost; + NSUInteger _maxRunningFetchersPerHost; + + // When this ivar is nil, the service will not reuse sessions. + GTMSessionFetcherSessionDelegateDispatcher *_delegateDispatcher; + + // Fetchers will wait on this if another fetcher is creating the shared NSURLSession. + dispatch_semaphore_t _sessionCreationSemaphore; + + dispatch_queue_t _callbackQueue; + NSOperationQueue *_delegateQueue; + NSHTTPCookieStorage *_cookieStorage; + NSString *_userAgent; + NSTimeInterval _timeout; + + NSURLCredential *_credential; // Username & password. + NSURLCredential *_proxyCredential; // Credential supplied to proxy servers. + + NSInteger _cookieStorageMethod; + + id _authorizer; + + // For waitForCompletionOfAllFetchersWithTimeout: we need to wait on stopped fetchers since + // they've not yet finished invoking their queued callbacks. This array is nil except when + // waiting on fetchers. + NSMutableArray *_stoppedFetchersToWaitFor; + + // For fetchers that enqueued their callbacks before stopAllFetchers was called on the service, + // set a barrier so the callbacks know to bail out. + NSDate *_stoppedAllFetchersDate; +} + +@synthesize maxRunningFetchersPerHost = _maxRunningFetchersPerHost, + configuration = _configuration, + configurationBlock = _configurationBlock, + cookieStorage = _cookieStorage, + userAgent = _userAgent, + challengeBlock = _challengeBlock, + credential = _credential, + proxyCredential = _proxyCredential, + allowedInsecureSchemes = _allowedInsecureSchemes, + allowLocalhostRequest = _allowLocalhostRequest, + allowInvalidServerCertificates = _allowInvalidServerCertificates, + retryEnabled = _retryEnabled, + retryBlock = _retryBlock, + maxRetryInterval = _maxRetryInterval, + minRetryInterval = _minRetryInterval, + metricsCollectionBlock = _metricsCollectionBlock, + properties = _properties, + unusedSessionTimeout = _unusedSessionTimeout, + testBlock = _testBlock; + +#if GTM_BACKGROUND_TASK_FETCHING +@synthesize skipBackgroundTask = _skipBackgroundTask; +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _delayedFetchersByHost = [[NSMutableDictionary alloc] init]; + _runningFetchersByHost = [[NSMutableDictionary alloc] init]; + _maxRunningFetchersPerHost = 10; + _cookieStorageMethod = -1; + _unusedSessionTimeout = 60.0; + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + _callbackQueue = dispatch_get_main_queue(); + + _delegateQueue = [[NSOperationQueue alloc] init]; + _delegateQueue.maxConcurrentOperationCount = 1; + _delegateQueue.name = @"com.google.GTMSessionFetcher.NSURLSessionDelegateQueue"; + + _sessionCreationSemaphore = dispatch_semaphore_create(1); + + // Starting with the SDKs for OS X 10.11/iOS 9, the service has a default useragent. + // Apps can remove this and get the default system "CFNetwork" useragent by setting the + // fetcher service's userAgent property to nil. +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0) + _userAgent = GTMFetcherStandardUserAgentString(nil); +#endif + } + return self; +} + +- (void)dealloc { + [self detachAuthorizer]; + [_delegateDispatcher abandon]; +} + +#pragma mark Generate a new fetcher + +// Clients may override this method. Clients should not override any other library methods. +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass { + GTMSessionFetcher *fetcher = [[fetcherClass alloc] initWithRequest:request + configuration:self.configuration]; + fetcher.callbackQueue = self.callbackQueue; + fetcher.sessionDelegateQueue = self.sessionDelegateQueue; + fetcher.challengeBlock = self.challengeBlock; + fetcher.credential = self.credential; + fetcher.proxyCredential = self.proxyCredential; + fetcher.authorizer = self.authorizer; + fetcher.cookieStorage = self.cookieStorage; + fetcher.allowedInsecureSchemes = self.allowedInsecureSchemes; + fetcher.allowLocalhostRequest = self.allowLocalhostRequest; + fetcher.allowInvalidServerCertificates = self.allowInvalidServerCertificates; + fetcher.configurationBlock = self.configurationBlock; + fetcher.retryEnabled = self.retryEnabled; + fetcher.retryBlock = self.retryBlock; + fetcher.maxRetryInterval = self.maxRetryInterval; + fetcher.minRetryInterval = self.minRetryInterval; + if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) { + fetcher.metricsCollectionBlock = self.metricsCollectionBlock; + } + fetcher.properties = self.properties; + fetcher.service = self; + if (self.cookieStorageMethod >= 0) { + [fetcher setCookieStorageMethod:self.cookieStorageMethod]; + } + +#if GTM_BACKGROUND_TASK_FETCHING + fetcher.skipBackgroundTask = self.skipBackgroundTask; +#endif + + NSString *userAgent = self.userAgent; + if (userAgent.length > 0 + && [request valueForHTTPHeaderField:@"User-Agent"] == nil) { + [fetcher setRequestValue:userAgent + forHTTPHeaderField:@"User-Agent"]; + } + fetcher.testBlock = self.testBlock; + + return fetcher; +} + +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request { + return [self fetcherWithRequest:request + fetcherClass:[GTMSessionFetcher class]]; +} + +- (GTMSessionFetcher *)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + +- (GTMSessionFetcher *)fetcherWithURLString:(NSString *)requestURLString { + NSURL *url = [NSURL URLWithString:requestURLString]; + return [self fetcherWithURL:url]; +} + +// Returns a session for the fetcher's host, or nil. +- (NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLSession *session = _delegateDispatcher.session; + return session; + } +} + +// Returns a session for the fetcher's host, or nil. For shared sessions, this +// waits on a semaphore, blocking other fetchers while the caller creates the +// session if needed. +- (NSURLSession *)sessionForFetcherCreation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + if (!_delegateDispatcher) { + // This fetcher is creating a non-shared session, so skip the semaphore usage. + return nil; + } + } + + // Wait if another fetcher is currently creating a session; avoid waiting + // inside the @synchronized block, as that can deadlock. + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Before getting the NSURLSession for task creation, it is + // important to invalidate and nil out the session discard timer; otherwise + // the session can be invalidated between when it is returned to the + // fetcher, and when the fetcher attempts to create its NSURLSessionTask. + [_delegateDispatcher startSessionUsage]; + + NSURLSession *session = _delegateDispatcher.session; + if (session) { + // The calling fetcher will receive a preexisting session, so + // we can allow other fetchers to create a session. + dispatch_semaphore_signal(_sessionCreationSemaphore); + } else { + // No existing session was obtained, so the calling fetcher will create the session; + // it *must* invoke fetcherDidCreateSession: to signal the dispatcher's semaphore after + // the session has been created (or fails to be created) to avoid a hang. + } + return session; + } +} + +- (id)sessionDelegate { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateDispatcher; + } +} + +#pragma mark Queue Management + +- (void)addRunningFetcher:(GTMSessionFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of running fetchers for this host, creating the array if needed. + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + if (runningForHost == nil) { + runningForHost = [NSMutableArray arrayWithObject:fetcher]; + [_runningFetchersByHost setObject:runningForHost forKey:host]; + } else { + [runningForHost addObject:fetcher]; + } +} + +- (void)addDelayedFetcher:(GTMSessionFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of delayed fetchers for this host, creating the array if needed. + NSMutableArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + if (delayedForHost == nil) { + delayedForHost = [NSMutableArray arrayWithObject:fetcher]; + [_delayedFetchersByHost setObject:delayedForHost forKey:host]; + } else { + [delayedForHost addObject:fetcher]; + } +} + +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSString *host = fetcher.request.URL.host; + if (host == nil) { + return NO; + } + NSArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + NSUInteger idx = [delayedForHost indexOfObjectIdenticalTo:fetcher]; + BOOL isDelayed = (delayedForHost != nil) && (idx != NSNotFound); + return isDelayed; + } +} + +- (BOOL)fetcherShouldBeginFetching:(GTMSessionFetcher *)fetcher { + // Entry point from the fetcher + NSURL *requestURL = fetcher.request.URL; + NSString *host = requestURL.host; + + // Addresses "file:///path" case where localhost is the implicit host. + if (host.length == 0 && [requestURL isFileURL]) { + host = @"localhost"; + } + + if (host.length == 0) { + // Data URIs legitimately have no host, reject other hostless URLs. + GTMSESSION_ASSERT_DEBUG([[requestURL scheme] isEqual:@"data"], @"%@ lacks host", fetcher); + return YES; + } + + BOOL shouldBeginResult; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + if (runningForHost != nil + && [runningForHost indexOfObjectIdenticalTo:fetcher] != NSNotFound) { + GTMSESSION_ASSERT_DEBUG(NO, @"%@ was already running", fetcher); + return YES; + } + + BOOL shouldRunNow = (fetcher.usingBackgroundSession + || _maxRunningFetchersPerHost == 0 + || _maxRunningFetchersPerHost > + [[self class] numberOfNonBackgroundSessionFetchers:runningForHost]); + if (shouldRunNow) { + [self addRunningFetcher:fetcher forHost:host]; + shouldBeginResult = YES; + } else { + [self addDelayedFetcher:fetcher forHost:host]; + shouldBeginResult = NO; + } + } // @synchronized(self) + + // We'll save the host that serves as the key for this fetcher's array + // to avoid any chance of the underlying request changing, stranding + // the fetcher in the wrong array + fetcher.serviceHost = host; + + return shouldBeginResult; +} + +- (void)startFetcher:(GTMSessionFetcher *)fetcher { + [fetcher beginFetchMayDelay:NO + mayAuthorize:YES]; +} + +// Internal utility. Returns a fetcher's delegate if it's a dispatcher, or nil if the fetcher +// is its own delegate (possibly via proxy) and has no dispatcher. +- (GTMSessionFetcherSessionDelegateDispatcher *)delegateDispatcherForFetcher:(GTMSessionFetcher *)fetcher { + GTMSessionCheckNotSynchronized(self); + + NSURLSession *fetcherSession = fetcher.session; + if (fetcherSession) { + id fetcherDelegate = fetcherSession.delegate; + // If the delegate is non-nil and claims to be a GTMSessionFetcher, there is no dispatcher; + // assume the fetcher is the delegate or has been proxied (some third-party frameworks + // are known to swizzle NSURLSession to proxy its delegate). + BOOL hasDispatcher = (fetcherDelegate != nil && + ![fetcherDelegate isKindOfClass:[GTMSessionFetcher class]]); + if (hasDispatcher) { + GTMSESSION_ASSERT_DEBUG([fetcherDelegate isKindOfClass:[GTMSessionFetcherSessionDelegateDispatcher class]], + @"Fetcher delegate class: %@", [fetcherDelegate class]); + return (GTMSessionFetcherSessionDelegateDispatcher *)fetcherDelegate; + } + } + return nil; +} + +- (void)fetcherDidCreateSession:(GTMSessionFetcher *)fetcher { + if (fetcher.canShareSession) { + NSURLSession *fetcherSession = fetcher.session; + GTMSESSION_ASSERT_DEBUG(fetcherSession != nil, @"Fetcher missing its session: %@", fetcher); + + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + if (delegateDispatcher) { + GTMSESSION_ASSERT_DEBUG(delegateDispatcher.session == nil, + @"Fetcher made an extra session: %@", fetcher); + + // Save this fetcher's session. + delegateDispatcher.session = fetcherSession; + + // Allow other fetchers to request this session now. + dispatch_semaphore_signal(_sessionCreationSemaphore); + } + } +} + +- (void)fetcherDidBeginFetching:(GTMSessionFetcher *)fetcher { + // If this fetcher has a separate delegate with a shared session, then + // this fetcher should be added to the delegate's map of tasks to fetchers. + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + if (delegateDispatcher) { + GTMSESSION_ASSERT_DEBUG(fetcher.canShareSession, + @"Inappropriate shared session: %@", fetcher); + + // There should already be a session, from this or a previous fetcher. + // + // Sanity check that the fetcher's session is the delegate's shared session. + NSURLSession *sharedSession = delegateDispatcher.session; + NSURLSession *fetcherSession = fetcher.session; + GTMSESSION_ASSERT_DEBUG(sharedSession != nil, @"Missing delegate session: %@", fetcher); + GTMSESSION_ASSERT_DEBUG(fetcherSession == sharedSession, + @"Inconsistent session: %@ %@ (shared: %@)", + fetcher, fetcherSession, sharedSession); + + if (sharedSession != nil && fetcherSession == sharedSession) { + NSURLSessionTask *task = fetcher.sessionTask; + GTMSESSION_ASSERT_DEBUG(task != nil, @"Missing session task: %@", fetcher); + + if (task) { + [delegateDispatcher setFetcher:fetcher + forTask:task]; + } + } + } +} + +- (void)stopFetcher:(GTMSessionFetcher *)fetcher { + [fetcher stopFetching]; +} + +- (void)fetcherDidStop:(GTMSessionFetcher *)fetcher { + // Entry point from the fetcher + NSString *host = fetcher.serviceHost; + if (!host) { + // fetcher has been stopped previously + return; + } + + // This removeFetcher: invocation is a fallback; typically, fetchers are removed from the task + // map when the task completes. + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + [delegateDispatcher removeFetcher:fetcher]; + + NSMutableArray *fetchersToStart; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // If a test is waiting for all fetchers to stop, it needs to wait for this one + // to invoke its callbacks on the callback queue. + [_stoppedFetchersToWaitFor addObject:fetcher]; + + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + [runningForHost removeObject:fetcher]; + + NSMutableArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + [delayedForHost removeObject:fetcher]; + + while (delayedForHost.count > 0 + && [[self class] numberOfNonBackgroundSessionFetchers:runningForHost] + < _maxRunningFetchersPerHost) { + // Start another delayed fetcher running, scanning for the minimum + // priority value, defaulting to FIFO for equal priorities + GTMSessionFetcher *nextFetcher = nil; + for (GTMSessionFetcher *delayedFetcher in delayedForHost) { + if (nextFetcher == nil + || delayedFetcher.servicePriority < nextFetcher.servicePriority) { + nextFetcher = delayedFetcher; + } + } + + if (nextFetcher) { + [self addRunningFetcher:nextFetcher forHost:host]; + runningForHost = [_runningFetchersByHost objectForKey:host]; + + [delayedForHost removeObjectIdenticalTo:nextFetcher]; + + if (!fetchersToStart) { + fetchersToStart = [NSMutableArray array]; + } + [fetchersToStart addObject:nextFetcher]; + } + } + + if (runningForHost.count == 0) { + // None left; remove the empty array + [_runningFetchersByHost removeObjectForKey:host]; + } + + if (delayedForHost.count == 0) { + [_delayedFetchersByHost removeObjectForKey:host]; + } + } // @synchronized(self) + + // Start fetchers outside of the synchronized block to avoid a deadlock. + for (GTMSessionFetcher *nextFetcher in fetchersToStart) { + [self startFetcher:nextFetcher]; + } + + // The fetcher is no longer in the running or the delayed array, + // so remove its host and thread properties + fetcher.serviceHost = nil; +} + +- (NSUInteger)numberOfFetchers { + NSUInteger running = [self numberOfRunningFetchers]; + NSUInteger delayed = [self numberOfDelayedFetchers]; + return running + delayed; +} + +- (NSUInteger)numberOfRunningFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger sum = 0; + for (NSString *host in _runningFetchersByHost) { + NSArray *fetchers = [_runningFetchersByHost objectForKey:host]; + sum += fetchers.count; + } + return sum; + } +} + +- (NSUInteger)numberOfDelayedFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger sum = 0; + for (NSString *host in _delayedFetchersByHost) { + NSArray *fetchers = [_delayedFetchersByHost objectForKey:host]; + sum += fetchers.count; + } + return sum; + } +} + +- (NSArray *)issuedFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSMutableArray *allFetchers = [NSMutableArray array]; + void (^accumulateFetchers)(id, id, BOOL *) = ^(NSString *host, + NSArray *fetchersForHost, + BOOL *stop) { + [allFetchers addObjectsFromArray:fetchersForHost]; + }; + [_runningFetchersByHost enumerateKeysAndObjectsUsingBlock:accumulateFetchers]; + [_delayedFetchersByHost enumerateKeysAndObjectsUsingBlock:accumulateFetchers]; + + GTMSESSION_ASSERT_DEBUG(allFetchers.count == [NSSet setWithArray:allFetchers].count, + @"Fetcher appears multiple times\n running: %@\n delayed: %@", + _runningFetchersByHost, _delayedFetchersByHost); + + return allFetchers.count > 0 ? allFetchers : nil; + } +} + +- (NSArray *)issuedFetchersWithRequestURL:(NSURL *)requestURL { + NSString *host = requestURL.host; + if (host.length == 0) return nil; + + NSURL *targetURL = [requestURL absoluteURL]; + + NSArray *allFetchers = [self issuedFetchers]; + NSIndexSet *indexes = [allFetchers indexesOfObjectsPassingTest:^BOOL(GTMSessionFetcher *fetcher, + NSUInteger idx, + BOOL *stop) { + NSURL *fetcherURL = [fetcher.request.URL absoluteURL]; + return [fetcherURL isEqual:targetURL]; + }]; + + NSArray *result = nil; + if (indexes.count > 0) { + result = [allFetchers objectsAtIndexes:indexes]; + } + return result; +} + +- (void)stopAllFetchers { + NSArray *delayedFetchersByHost; + NSArray *runningFetchersByHost; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Set the time barrier so fetchers know not to call back even if + // the stop calls below occur after the fetchers naturally + // stopped and so were removed from _runningFetchersByHost, + // but while the callbacks were already enqueued before stopAllFetchers + // was invoked. + _stoppedAllFetchersDate = [[NSDate alloc] init]; + + // Remove fetchers from the delayed list to avoid fetcherDidStop: from + // starting more fetchers running as a side effect of stopping one + delayedFetchersByHost = _delayedFetchersByHost.allValues; + [_delayedFetchersByHost removeAllObjects]; + + runningFetchersByHost = _runningFetchersByHost.allValues; + [_runningFetchersByHost removeAllObjects]; + } + + for (NSArray *delayedForHost in delayedFetchersByHost) { + for (GTMSessionFetcher *fetcher in delayedForHost) { + [self stopFetcher:fetcher]; + } + } + + for (NSArray *runningForHost in runningFetchersByHost) { + for (GTMSessionFetcher *fetcher in runningForHost) { + [self stopFetcher:fetcher]; + } + } +} + +- (NSDate *)stoppedAllFetchersDate { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _stoppedAllFetchersDate; + } +} + +#pragma mark Accessors + +- (BOOL)reuseSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateDispatcher != nil; + } +} + +- (void)setReuseSession:(BOOL)shouldReuse { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL wasReusing = (_delegateDispatcher != nil); + if (shouldReuse != wasReusing) { + [self abandonDispatcher]; + if (shouldReuse) { + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + } else { + _delegateDispatcher = nil; + } + } + } +} + +- (void)resetSession { + GTMSessionCheckNotSynchronized(self); + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + [self resetSessionInternal]; + } + + dispatch_semaphore_signal(_sessionCreationSemaphore); +} + +- (void)resetSessionInternal { + GTMSessionCheckSynchronized(self); + + // The old dispatchers may be retained as delegates of any ongoing sessions by those sessions. + if (_delegateDispatcher) { + [self abandonDispatcher]; + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + } +} + +- (void)resetSessionForDispatcherDiscardTimer:(NSTimer *)timer { + GTMSessionCheckNotSynchronized(self); + + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_delegateDispatcher.discardTimer == timer) { + // If the delegate dispatcher's current discardTimer is the same object as the timer + // that fired, no fetcher has recently attempted to start using the session by calling + // startSessionUsage, which invalidates and nils out the timer. + [self resetSessionInternal]; + } else { + // A fetcher has invalidated the timer between its triggering and now, potentially + // meaning a fetcher has requested access to the NSURLSession, and may be in the process + // of starting a new task. The dispatcher should not be abandoned, as this can lead + // to a race condition between calling -finishTasksAndInvalidate on the NSURLSession + // and the fetcher attempting to create a new task. + } + } + + dispatch_semaphore_signal(_sessionCreationSemaphore); +} + +- (NSTimeInterval)unusedSessionTimeout { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _unusedSessionTimeout; + } +} + +- (void)setUnusedSessionTimeout:(NSTimeInterval)timeout { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _unusedSessionTimeout = timeout; + _delegateDispatcher.discardInterval = timeout; + } +} + +// This method should be called inside of @synchronized(self) +- (void)abandonDispatcher { + GTMSessionCheckSynchronized(self); + [_delegateDispatcher abandon]; +} + +- (NSDictionary *)runningFetchersByHost { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_runningFetchersByHost copy]; + } +} + +- (void)setRunningFetchersByHost:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _runningFetchersByHost = [dict mutableCopy]; + } +} + +- (NSDictionary *)delayedFetchersByHost { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_delayedFetchersByHost copy]; + } +} + +- (void)setDelayedFetchersByHost:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delayedFetchersByHost = [dict mutableCopy]; + } +} + +- (id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _authorizer; + } +} + +- (void)setAuthorizer:(id)obj { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (obj != _authorizer) { + [self detachAuthorizer]; + } + + _authorizer = obj; + } + + // Use the fetcher service for the authorization fetches if the auth + // object supports fetcher services + if ([obj respondsToSelector:@selector(setFetcherService:)]) { +#if GTM_USE_SESSION_FETCHER + [obj setFetcherService:self]; +#else + [obj setFetcherService:(id)self]; +#endif + } +} + +// This should be called inside a @synchronized(self) block except during dealloc. +- (void)detachAuthorizer { + // This method is called by the fetcher service's dealloc and setAuthorizer: + // methods; do not override. + // + // The fetcher service retains the authorizer, and the authorizer has a + // weak pointer to the fetcher service (a non-zeroing pointer for + // compatibility with iOS 4 and Mac OS X 10.5/10.6.) + // + // When this fetcher service no longer uses the authorizer, we want to remove + // the authorizer's dependence on the fetcher service. Authorizers can still + // function without a fetcher service. + if ([_authorizer respondsToSelector:@selector(fetcherService)]) { + id authFetcherService = [_authorizer fetcherService]; + if (authFetcherService == self) { + [_authorizer setFetcherService:nil]; + } + } +} + +- (dispatch_queue_t GTM_NONNULL_TYPE)callbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _callbackQueue; + } // @synchronized(self) +} + +- (void)setCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _callbackQueue = queue ?: dispatch_get_main_queue(); + } // @synchronized(self) +} + +- (NSOperationQueue * GTM_NONNULL_TYPE)sessionDelegateQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateQueue; + } // @synchronized(self) +} + +- (void)setSessionDelegateQueue:(NSOperationQueue * GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateQueue = queue ?: [NSOperationQueue mainQueue]; + } // @synchronized(self) +} + +- (NSOperationQueue *)delegateQueue { + // Provided for compatibility with the old fetcher service. The gtm-oauth2 code respects + // any custom delegate queue for calling the app. + return nil; +} + ++ (NSUInteger)numberOfNonBackgroundSessionFetchers:(NSArray *)fetchers { + NSUInteger sum = 0; + for (GTMSessionFetcher *fetcher in fetchers) { + if (!fetcher.usingBackgroundSession) { + ++sum; + } + } + return sum; +} + +@end + +@implementation GTMSessionFetcherService (TestingSupport) + ++ (instancetype)mockFetcherServiceWithFakedData:(NSData *)fakedDataOrNil + fakedError:(NSError *)fakedErrorOrNil { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + NSURL *url = [NSURL URLWithString:@"http://example.invalid"]; + NSHTTPURLResponse *fakedResponse = + [[NSHTTPURLResponse alloc] initWithURL:url + statusCode:(fakedErrorOrNil ? 500 : 200) + HTTPVersion:@"HTTP/1.1" + headerFields:nil]; + return [self mockFetcherServiceWithFakedData:fakedDataOrNil + fakedResponse:fakedResponse + fakedError:fakedErrorOrNil]; +#else + GTMSESSION_ASSERT_DEBUG(0, @"Test blocks disabled"); + return nil; +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK +} + ++ (instancetype)mockFetcherServiceWithFakedData:(NSData *)fakedDataOrNil + fakedResponse:(NSHTTPURLResponse *)fakedResponse + fakedError:(NSError *)fakedErrorOrNil { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSessionFetcherService *service = [[self alloc] init]; + service.allowedInsecureSchemes = @[ @"http" ]; + service.testBlock = ^(GTMSessionFetcher *fetcherToTest, + GTMSessionFetcherTestResponse testResponse) { + testResponse(fakedResponse, fakedDataOrNil, fakedErrorOrNil); + }; + return service; +#else + GTMSESSION_ASSERT_DEBUG(0, @"Test blocks disabled"); + return nil; +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK +} + +#pragma mark Synchronous Wait for Unit Testing + +- (BOOL)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate *giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + _stoppedFetchersToWaitFor = [NSMutableArray array]; + + BOOL shouldSpinRunLoop = [NSThread isMainThread]; + const NSTimeInterval kSpinInterval = 0.001; + BOOL didTimeOut = NO; + while (([self numberOfFetchers] > 0 || _stoppedFetchersToWaitFor.count > 0)) { + didTimeOut = [giveUpDate timeIntervalSinceNow] < 0; + if (didTimeOut) break; + + GTMSessionFetcher *stoppedFetcher = _stoppedFetchersToWaitFor.firstObject; + if (stoppedFetcher) { + [_stoppedFetchersToWaitFor removeObject:stoppedFetcher]; + [stoppedFetcher waitForCompletionWithTimeout:10.0 * kSpinInterval]; + } + + if (shouldSpinRunLoop) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:kSpinInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + [NSThread sleepForTimeInterval:kSpinInterval]; + } + } + _stoppedFetchersToWaitFor = nil; + + return !didTimeOut; +} + +@end + +@implementation GTMSessionFetcherService (BackwardsCompatibilityOnly) + +- (NSInteger)cookieStorageMethod { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _cookieStorageMethod; + } +} + +- (void)setCookieStorageMethod:(NSInteger)cookieStorageMethod { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _cookieStorageMethod = cookieStorageMethod; + } +} + +@end + +@implementation GTMSessionFetcherSessionDelegateDispatcher { + __weak GTMSessionFetcherService *_parentService; + NSURLSession *_session; + + // The task map maps NSURLSessionTasks to GTMSessionFetchers + NSMutableDictionary *_taskToFetcherMap; + // The discard timer will invalidate sessions after the session's last task completes. + NSTimer *_discardTimer; + NSTimeInterval _discardInterval; +} + +@synthesize discardInterval = _discardInterval, + session = _session; + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (instancetype)initWithParentService:(GTMSessionFetcherService *)parentService + sessionDiscardInterval:(NSTimeInterval)discardInterval { + self = [super init]; + if (self) { + _discardInterval = discardInterval; + _parentService = parentService; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p %@ %@", + [self class], self, + _session ?: @"", + _taskToFetcherMap.count > 0 ? _taskToFetcherMap : @""]; +} + +- (NSTimer *)discardTimer { + GTMSessionCheckNotSynchronized(self); + @synchronized(self) { + return _discardTimer; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)startDiscardTimer { + GTMSessionCheckSynchronized(self); + [_discardTimer invalidate]; + _discardTimer = nil; + if (_discardInterval > 0) { + _discardTimer = [NSTimer timerWithTimeInterval:_discardInterval + target:self + selector:@selector(discardTimerFired:) + userInfo:nil + repeats:NO]; + [_discardTimer setTolerance:(_discardInterval / 10)]; + [[NSRunLoop mainRunLoop] addTimer:_discardTimer forMode:NSRunLoopCommonModes]; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)destroyDiscardTimer { + GTMSessionCheckSynchronized(self); + [_discardTimer invalidate]; + _discardTimer = nil; +} + +- (void)discardTimerFired:(NSTimer *)timer { + GTMSessionFetcherService *service; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger numberOfTasks = _taskToFetcherMap.count; + if (numberOfTasks == 0) { + service = _parentService; + } + } + + // Inform the service that the discard timer has fired, and should check whether the + // service can abandon us. -resetSession cannot be called directly, as there is a + // race condition that must be guarded against with the NSURLSession being returned + // from sessionForFetcherCreation outside other locks. The service can take steps + // to prevent resetting the session if that has occurred. + // + // The service must be called from outside the @synchronized block. + [service resetSessionForDispatcherDiscardTimer:timer]; +} + +- (void)abandon { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self destroySessionAndTimer]; + } +} + +- (void)startSessionUsage { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self destroyDiscardTimer]; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)destroySessionAndTimer { + GTMSessionCheckSynchronized(self); + [self destroyDiscardTimer]; + + // Break any retain cycle from the session holding the delegate. + [_session finishTasksAndInvalidate]; + + // Immediately clear the session so no new task may be issued with it. + // + // The _taskToFetcherMap needs to stay valid until the outstanding tasks finish. + _session = nil; +} + +- (void)setFetcher:(GTMSessionFetcher *)fetcher forTask:(NSURLSessionTask *)task { + GTMSESSION_ASSERT_DEBUG(fetcher != nil, @"missing fetcher"); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_taskToFetcherMap == nil) { + _taskToFetcherMap = [[NSMutableDictionary alloc] init]; + } + + if (fetcher) { + [_taskToFetcherMap setObject:fetcher forKey:task]; + [self destroyDiscardTimer]; + } + } +} + +- (void)removeFetcher:(GTMSessionFetcher *)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Typically, a fetcher should be removed when its task invokes + // URLSession:task:didCompleteWithError:. + // + // When fetching with a testBlock, though, the task completed delegate + // method may not be invoked, requiring cleanup here. + NSArray *tasks = [_taskToFetcherMap allKeysForObject:fetcher]; + GTMSESSION_ASSERT_DEBUG(tasks.count <= 1, @"fetcher task not unmapped: %@", tasks); + [_taskToFetcherMap removeObjectsForKeys:tasks]; + + if (_taskToFetcherMap.count == 0) { + [self startDiscardTimer]; + } + } +} + +// This helper method provides synchronized access to the task map for the delegate +// methods below. +- (id)fetcherForTask:(NSURLSessionTask *)task { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_taskToFetcherMap objectForKey:task]; + } +} + +- (void)removeTaskFromMap:(NSURLSessionTask *)task { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_taskToFetcherMap removeObjectForKey:task]; + } +} + +- (void)setSession:(NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = session; + } +} + +- (NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _session; + } +} + +- (NSTimeInterval)discardInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _discardInterval; + } +} + +- (void)setDiscardInterval:(NSTimeInterval)interval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _discardInterval = interval; + } +} + +// NSURLSessionDelegate protocol methods. + +// - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session; +// +// TODO(seh): How do we route this to an appropriate fetcher? + + +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ didBecomeInvalidWithError:%@", + [self class], self, session, error); + NSDictionary *localTaskToFetcherMap; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = nil; + + localTaskToFetcherMap = [_taskToFetcherMap copy]; + } + + // Any "suspended" tasks may not have received callbacks from NSURLSession when the session + // completes; we'll call them now. + [localTaskToFetcherMap enumerateKeysAndObjectsUsingBlock:^(NSURLSessionTask *task, + GTMSessionFetcher *fetcher, + BOOL *stop) { + if (fetcher.session == session) { + // Our delegate method URLSession:task:didCompleteWithError: will rely on + // _taskToFetcherMap so that should still contain this fetcher. + NSError *canceledError = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorCancelled + userInfo:nil]; + [self URLSession:session task:task didCompleteWithError:canceledError]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"Unexpected session in fetcher: %@ has %@ (expected %@)", + fetcher, fetcher.session, session); + } + }]; + + // Our tests rely on this notification to know the session discard timer fired. + NSDictionary *userInfo = @{ kGTMSessionFetcherServiceSessionKey : session }; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMSessionFetcherServiceSessionBecameInvalidNotification + object:_parentService + userInfo:userInfo]; +} + + +#pragma mark - NSURLSessionTaskDelegate + +// NSURLSessionTaskDelegate protocol methods. +// +// We won't test here if the fetcher responds to these since we only want this +// class to implement the same delegate methods the fetcher does (so NSURLSession's +// tests for respondsToSelector: will have the same result whether the session +// delegate is the fetcher or this dispatcher.) + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task +willPerformHTTPRedirection:response + newRequest:request + completionHandler:completionHandler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))handler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + didReceiveChallenge:challenge + completionHandler:handler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + needNewBodyStream:(void (^)(NSInputStream *bodyStream))handler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + needNewBodyStream:handler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + didSendBodyData:bytesSent + totalBytesSent:totalBytesSent +totalBytesExpectedToSend:totalBytesExpectedToSend]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(NSError *)error { + id fetcher = [self fetcherForTask:task]; + + // This is the usual way tasks are removed from the task map. + [self removeTaskFromMap:task]; + + [fetcher URLSession:session + task:task + didCompleteWithError:error]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics + API_AVAILABLE(ios(10.0), macosx(10.12), tvos(10.0), watchos(3.0)) { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session task:task didFinishCollectingMetrics:metrics]; +} + +// NSURLSessionDataDelegate protocol methods. + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition))handler { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + didReceiveResponse:response + completionHandler:handler]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { + id fetcher = [self fetcherForTask:dataTask]; + GTMSESSION_ASSERT_DEBUG(fetcher != nil, @"Missing fetcher for %@", dataTask); + [self removeTaskFromMap:dataTask]; + if (fetcher) { + GTMSESSION_ASSERT_DEBUG([fetcher isKindOfClass:[GTMSessionFetcher class]], + @"Expecting GTMSessionFetcher"); + [self setFetcher:(GTMSessionFetcher *)fetcher forTask:downloadTask]; + } + + [fetcher URLSession:session + dataTask:dataTask +didBecomeDownloadTask:downloadTask]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + didReceiveData:data]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse *))handler { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + willCacheResponse:proposedResponse + completionHandler:handler]; +} + +// NSURLSessionDownloadDelegate protocol methods. + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask +didFinishDownloadingToURL:(NSURL *)location { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask +didFinishDownloadingToURL:location]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didWriteData:(int64_t)bytesWritten + totalBytesWritten:(int64_t)totalWritten +totalBytesExpectedToWrite:(int64_t)totalExpected { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask + didWriteData:bytesWritten + totalBytesWritten:totalWritten +totalBytesExpectedToWrite:totalExpected]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didResumeAtOffset:(int64_t)fileOffset +expectedTotalBytes:(int64_t)expectedTotalBytes { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask + didResumeAtOffset:fileOffset + expectedTotalBytes:expectedTotalBytes]; +} + +@end diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h new file mode 100644 index 00000000..2f9023a9 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h @@ -0,0 +1,175 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// GTMSessionUploadFetcher implements Google's resumable upload protocol. + +// +// This subclass of GTMSessionFetcher simulates the series of fetches +// needed for chunked upload as a single fetch operation. +// +// Protocol document: TBD +// +// To the client, the only fetcher that exists is this class; the subsidiary +// fetchers needed for uploading chunks are not visible (though the most recent +// chunk fetcher may be accessed via the -activeFetcher or -chunkFetcher methods, and +// -responseHeaders and -statusCode reflect results from the most recent chunk +// fetcher.) +// +// Chunk fetchers are discarded as soon as they have completed. +// +// The protocol also allows for a cancellation notification request to be sent to the +// server to allow discarding of the currently uploaded data and this will be sent +// automatically upon calling stopFetching if the upload has already started. +// +// Note: Unlike the fetcher superclass, the methods of GTMSessionUploadFetcher should +// only be used from the main thread until further work is done to make this subclass +// thread-safe. + +#import "GTMSessionFetcher.h" +#import "GTMSessionFetcherService.h" + +GTM_ASSUME_NONNULL_BEGIN + +// The value to use for file size parameters when the file size is not yet known. +extern int64_t const kGTMSessionUploadFetcherUnknownFileSize; + +// Unless an application knows it needs a smaller chunk size, it should use the standard +// chunk size, which sends the entire file as a single chunk to minimize upload overhead. +// Setting an explicit chunk size that comfortably fits in memory is advisable for large +// uploads. +extern int64_t const kGTMSessionUploadFetcherStandardChunkSize; + +// When uploading requires data buffer allocations (such as uploading from an NSData or +// an NSFileHandle) this is the maximum buffer size that will be created by the fetcher. +extern int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize; + +// Notification that the upload location URL was provided by the server. +extern NSString *const kGTMSessionFetcherUploadLocationObtainedNotification; + +// Block to provide data during uploads. +// +// Response data may be allocated with dataWithBytesNoCopy:length:freeWhenDone: for efficiency, +// and released after the response block returns. +// +// If the length of the file being uploaded is unknown or already set, send +// kGTMSessionUploadFetcherUnknownFileSize for |fullUploadLength|. Otherwise, set |fullUploadLength| +// to its proper value. +// +// Pass nil as the data (and optionally an NSError) for a failure. +typedef void (^GTMSessionUploadFetcherDataProviderResponse)(NSData * GTM_NULLABLE_TYPE data, + int64_t fullUploadLength, + NSError * GTM_NULLABLE_TYPE error); +// Do not call the response with an NSData object with less data than the requested length unless +// you are passing the fullUploadLength to the fetcher for the first time and it is the last chunk +// of data in the file being uploaded. +typedef void (^GTMSessionUploadFetcherDataProvider)(int64_t offset, int64_t length, + GTMSessionUploadFetcherDataProviderResponse response); + +// Block to be notified about the final status of the cancellation request started in stopFetching. +// +// |fetcher| will be the cancel request that was sent to the server, or nil if stopFetching is not +// going to send a cancel request. If |fetcher| is provided, the other parameters correspond to the +// completion handler of the cancellation request fetcher. +typedef void (^GTMSessionUploadFetcherCancellationHandler)( + GTMSessionFetcher * GTM_NULLABLE_TYPE fetcher, + NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); + +@interface GTMSessionUploadFetcher : GTMSessionFetcher + +// Create an upload fetcher specifying either the request or the resume location URL, +// then set an upload data source using one of these: +// +// setUploadFileURL: +// setUploadDataLength:provider: +// setUploadFileHandle: +// setUploadData: + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + +// Allows cellular access. ++ (instancetype)uploadFetcherWithLocation:(NSURL * GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + +// Allows dataProviders for files of unknown length. Pass kGTMSessionUploadFetcherUnknownFileSize as +// |fullLength| if the length is unknown. +- (void)setUploadDataLength:(int64_t)fullLength + provider:(GTM_NULLABLE GTMSessionUploadFetcherDataProvider)block; + ++ (NSArray *)uploadFetchersForBackgroundSessions; ++ (GTM_NULLABLE instancetype)uploadFetcherForSessionIdentifier:(NSString *)sessionIdentifier; + +- (void)pauseFetching; +- (void)resumeFetching; +- (BOOL)isPaused; + +@property(atomic, strong, GTM_NULLABLE) NSURL *uploadLocationURL; +@property(atomic, strong, GTM_NULLABLE) NSData *uploadData; +@property(atomic, strong, GTM_NULLABLE) NSURL *uploadFileURL; +@property(atomic, strong, GTM_NULLABLE) NSFileHandle *uploadFileHandle; +@property(atomic, copy, readonly, GTM_NULLABLE) GTMSessionUploadFetcherDataProvider uploadDataProvider; +@property(atomic, copy) NSString *uploadMIMEType; +@property(atomic, readonly, assign) int64_t chunkSize; +@property(atomic, readonly, assign) int64_t currentOffset; +// Reflects the original NSURLRequest's @c allowCellularAccess property. +@property(atomic, readonly, assign) BOOL allowsCellularAccess; + +// The fetcher for the current data chunk, if any +@property(atomic, strong, GTM_NULLABLE) GTMSessionFetcher *chunkFetcher; + +// The active fetcher is the current chunk fetcher, or the upload fetcher itself +// if no chunk fetcher has yet been created. +@property(atomic, readonly) GTMSessionFetcher *activeFetcher; + +// The last request made by an active fetcher. Useful for testing. +@property(atomic, readonly, GTM_NULLABLE) NSURLRequest *lastChunkRequest; + +// The status code from the most recently-completed fetch. +@property(atomic, assign) NSInteger statusCode; + +// Invoked as part of the stop fetching process. Invoked immediately if there is no upload in +// progress, otherwise invoked with the results of the attempt to notify the server that the +// upload will not continue. +// +// Unlike other callbacks, since this is related specifically to the stopFetching flow it is not +// cleared by stopFetching. It will instead clear itself after it is invoked or if the completion +// has occured before stopFetching is called. +@property(atomic, copy, GTM_NULLABLE) GTMSessionUploadFetcherCancellationHandler + cancellationHandler; + +// Exposed for testing only. +@property(atomic, readonly, GTM_NULLABLE) dispatch_queue_t delegateCallbackQueue; +@property(atomic, readonly, GTM_NULLABLE) GTMSessionFetcherCompletionHandler delegateCompletionHandler; + +@end + +@interface GTMSessionFetcher (GTMSessionUploadFetcherMethods) + +@property(readonly, GTM_NULLABLE) GTMSessionUploadFetcher *parentUploadFetcher; + +@end + +GTM_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m new file mode 100644 index 00000000..7759bb15 --- /dev/null +++ b/MyExperiences copy/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m @@ -0,0 +1,1989 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionUploadFetcher.h" + +static NSString *const kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey = @"_upChunk"; +static NSString *const kGTMSessionIdentifierUploadFileURLMetadataKey = @"_upFileURL"; +static NSString *const kGTMSessionIdentifierUploadFileLengthMetadataKey = @"_upFileLen"; +static NSString *const kGTMSessionIdentifierUploadLocationURLMetadataKey = @"_upLocURL"; +static NSString *const kGTMSessionIdentifierUploadMIMETypeMetadataKey = @"_uploadMIME"; +static NSString *const kGTMSessionIdentifierUploadChunkSizeMetadataKey = @"_upChSize"; +static NSString *const kGTMSessionIdentifierUploadCurrentOffsetMetadataKey = @"_upOffset"; +static NSString *const kGTMSessionIdentifierUploadAllowsCellularAccess = @"_upAllowsCellularAccess"; + +static NSString *const kGTMSessionHeaderXGoogUploadChunkGranularity = @"X-Goog-Upload-Chunk-Granularity"; +static NSString *const kGTMSessionHeaderXGoogUploadCommand = @"X-Goog-Upload-Command"; +static NSString *const kGTMSessionHeaderXGoogUploadContentLength = @"X-Goog-Upload-Content-Length"; +static NSString *const kGTMSessionHeaderXGoogUploadContentType = @"X-Goog-Upload-Content-Type"; +static NSString *const kGTMSessionHeaderXGoogUploadOffset = @"X-Goog-Upload-Offset"; +static NSString *const kGTMSessionHeaderXGoogUploadProtocol = @"X-Goog-Upload-Protocol"; +static NSString *const kGTMSessionXGoogUploadProtocolResumable = @"resumable"; +static NSString *const kGTMSessionHeaderXGoogUploadSizeReceived = @"X-Goog-Upload-Size-Received"; +static NSString *const kGTMSessionHeaderXGoogUploadStatus = @"X-Goog-Upload-Status"; +static NSString *const kGTMSessionHeaderXGoogUploadURL = @"X-Goog-Upload-URL"; + +// Property of chunk fetchers identifying the parent upload fetcher. Non-retained NSValue. +static NSString *const kGTMSessionUploadFetcherChunkParentKey = @"_uploadFetcherChunkParent"; + +int64_t const kGTMSessionUploadFetcherUnknownFileSize = -1; + +int64_t const kGTMSessionUploadFetcherStandardChunkSize = (int64_t)LLONG_MAX; + +#if TARGET_OS_IPHONE +int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize = 10 * 1024 * 1024; // 10 MB for iOS, watchOS, tvOS +#else +int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize = 100 * 1024 * 1024; // 100 MB for macOS +#endif + +typedef NS_ENUM(NSUInteger, GTMSessionUploadFetcherStatus) { + kStatusUnknown, + kStatusActive, + kStatusFinal, + kStatusCancelled, +}; + +NSString *const kGTMSessionFetcherUploadLocationObtainedNotification = + @"kGTMSessionFetcherUploadLocationObtainedNotification"; + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (ProtectedMethods) + +// Access to non-public method on the parent fetcher class. +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks; +- (void)createSessionIdentifierWithMetadata:(NSDictionary *)metadata; +- (GTMSessionFetcherCompletionHandler)completionHandlerWithTarget:(id)target + didFinishSelector:(SEL)finishedSelector; +- (void)invokeOnCallbackQueue:(dispatch_queue_t)callbackQueue + afterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block; +- (NSTimer *)retryTimer; +- (void)beginFetchForRetry; + +@property(readwrite, strong) NSData *downloadedData; +- (void)releaseCallbacks; + +- (NSInteger)statusCodeUnsynchronized; + +- (BOOL)userStoppedFetching; + +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionUploadFetcher () + +// Changing readonly to readwrite. +@property(atomic, strong, readwrite) NSURLRequest *lastChunkRequest; +@property(atomic, readwrite, assign) int64_t currentOffset; + +// Internal properties. +@property(strong, atomic, GTM_NULLABLE) GTMSessionFetcher *fetcherInFlight; // Synchronized on self. + +@property(assign, atomic, getter=isSubdataGenerating) BOOL subdataGenerating; +@property(assign, atomic) BOOL shouldInitiateOffsetQuery; +@property(assign, atomic) int64_t uploadGranularity; +@property(assign, atomic) BOOL allowsCellularAccess; + +@end + +@implementation GTMSessionUploadFetcher { + GTMSessionFetcher *_chunkFetcher; + + // We'll call through to the delegate's completion handler. + GTMSessionFetcherCompletionHandler _delegateCompletionHandler; + dispatch_queue_t _delegateCallbackQueue; + + // The initial fetch's body length and bytes actually sent are + // needed for calculating progress during subsequent chunk uploads + int64_t _initialBodyLength; + int64_t _initialBodySent; + + // The upload server address for the chunks of this upload session. + NSURL *_uploadLocationURL; + + // _uploadData, _uploadDataProvider, or _uploadFileHandle may be set, but only one. + NSData *_uploadData; + NSFileHandle *_uploadFileHandle; + GTMSessionUploadFetcherDataProvider _uploadDataProvider; + NSURL *_uploadFileURL; + int64_t _uploadFileLength; + NSString *_uploadMIMEType; + int64_t _chunkSize; + int64_t _uploadGranularity; + BOOL _isPaused; + BOOL _isRestartedUpload; + BOOL _shouldInitiateOffsetQuery; + + // Tied to useBackgroundSession property, since this property is applicable to chunk fetchers. + BOOL _useBackgroundSessionOnChunkFetchers; + + // We keep the latest offset into the upload data just for progress reporting. + int64_t _currentOffset; + + NSDictionary *_recentChunkReponseHeaders; + NSInteger _recentChunkStatusCode; + + // For waiting, we need to know the fetcher in flight, if any, and if subdata generation + // is in progress. + GTMSessionFetcher *_fetcherInFlight; + BOOL _isSubdataGenerating; + BOOL _isCancelInFlight; + + GTMSessionUploadFetcherCancellationHandler _cancellationHandler; +} + ++ (void)load { + [self uploadFetchersForBackgroundSessions]; +} + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTMSessionFetcherService *)fetcherService { + GTMSessionUploadFetcher *fetcher = [self uploadFetcherWithRequest:request + fetcherService:fetcherService]; + [fetcher setLocationURL:nil + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:request.allowsCellularAccess]; + return fetcher; +} + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil { + return [self uploadFetcherWithLocation:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:YES + fetcherService:fetcherServiceOrNil]; +} + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess + fetcherService:(GTMSessionFetcherService *)fetcherService { + GTMSessionUploadFetcher *fetcher = [self uploadFetcherWithRequest:nil + fetcherService:fetcherService]; + [fetcher setLocationURL:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:allowsCellularAccess]; + return fetcher; +} + ++ (instancetype)uploadFetcherForSessionIdentifierMetadata:(NSDictionary *)metadata { + GTMSESSION_ASSERT_DEBUG( + [metadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] boolValue], + @"Session identifier metadata is not for an upload fetcher: %@", metadata); + + NSNumber *uploadFileLengthNum = metadata[kGTMSessionIdentifierUploadFileLengthMetadataKey]; + GTMSESSION_ASSERT_DEBUG(uploadFileLengthNum != nil, + @"Session metadata missing an UploadFileSize"); + if (uploadFileLengthNum == nil) return nil; + + int64_t uploadFileLength = [uploadFileLengthNum longLongValue]; + GTMSESSION_ASSERT_DEBUG(uploadFileLength >= 0, @"Session metadata UploadFileSize is unknown"); + + NSString *uploadFileURLString = metadata[kGTMSessionIdentifierUploadFileURLMetadataKey]; + GTMSESSION_ASSERT_DEBUG(uploadFileURLString, @"Session metadata missing an UploadFileURL"); + if (uploadFileURLString == nil) return nil; + + NSURL *uploadFileURL = [NSURL URLWithString:uploadFileURLString]; + // There used to be a call here to NSURL checkResourceIsReachableAndReturnError: to check for the + // existence of the file (also tried NSFileManager fileExistsAtPath:). We've determined + // empirically that the check can fail at startup even when the upload file does in fact exist. + // For now, we'll go ahead and restore the background upload fetcher. If the file doesn't exist, + // it will fail later. + + NSString *uploadLocationURLString = metadata[kGTMSessionIdentifierUploadLocationURLMetadataKey]; + NSURL *uploadLocationURL = + uploadLocationURLString ? [NSURL URLWithString:uploadLocationURLString] : nil; + + NSString *uploadMIMEType = + metadata[kGTMSessionIdentifierUploadMIMETypeMetadataKey]; + int64_t uploadChunkSize = + [metadata[kGTMSessionIdentifierUploadChunkSizeMetadataKey] longLongValue]; + if (uploadChunkSize <= 0) { + uploadChunkSize = kGTMSessionUploadFetcherStandardChunkSize; + } + int64_t currentOffset = + [metadata[kGTMSessionIdentifierUploadCurrentOffsetMetadataKey] longLongValue]; + + BOOL allowsCellularAccess = YES; + if (metadata[kGTMSessionIdentifierUploadAllowsCellularAccess]) { + allowsCellularAccess = [metadata[kGTMSessionIdentifierUploadAllowsCellularAccess] boolValue]; + } + + GTMSESSION_ASSERT_DEBUG(currentOffset <= uploadFileLength, + @"CurrentOffset (%lld) exceeds UploadFileSize (%lld)", + currentOffset, uploadFileLength); + if (currentOffset > uploadFileLength) return nil; + + GTMSessionUploadFetcher *uploadFetcher = [self uploadFetcherWithLocation:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:uploadChunkSize + allowsCellularAccess:allowsCellularAccess + fetcherService:nil]; + // Set the upload file length before setting the upload file URL tries to determine the length. + [uploadFetcher setUploadFileLength:uploadFileLength]; + + uploadFetcher.uploadFileURL = uploadFileURL; + uploadFetcher.sessionUserInfo = metadata; + uploadFetcher.useBackgroundSession = YES; + uploadFetcher.currentOffset = currentOffset; + uploadFetcher.delegateCallbackQueue = uploadFetcher.callbackQueue; + uploadFetcher.allowedInsecureSchemes = @[ @"http" ]; // Allowed on restored upload fetcher. + return uploadFetcher; +} + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMSessionFetcherService *)fetcherService { + // Internal utility method for instantiating fetchers + GTMSessionUploadFetcher *fetcher; + if ([fetcherService isKindOfClass:[GTMSessionFetcherService class]]) { + fetcher = [fetcherService fetcherWithRequest:request + fetcherClass:self]; + } else { + fetcher = [self fetcherWithRequest:request]; + } + fetcher.useBackgroundSession = YES; + return fetcher; +} + ++ (NSPointerArray *)uploadFetcherPointerArrayForBackgroundSessions { + static NSPointerArray *gUploadFetcherPointerArrayForBackgroundSessions = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gUploadFetcherPointerArrayForBackgroundSessions = [NSPointerArray weakObjectsPointerArray]; + }); + return gUploadFetcherPointerArrayForBackgroundSessions; +} + ++ (instancetype)uploadFetcherForSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + NSArray *uploadFetchersForBackgroundSessions = [self uploadFetchersForBackgroundSessions]; + for (GTMSessionUploadFetcher *uploadFetcher in uploadFetchersForBackgroundSessions) { + if ([uploadFetcher.chunkFetcher.sessionIdentifier isEqual:sessionIdentifier]) { + return uploadFetcher; + } + } + return nil; +} + ++ (NSArray *)uploadFetchersForBackgroundSessions { + NSMutableSet *restoredSessionIdentifiers = [[NSMutableSet alloc] init]; + NSMutableArray *uploadFetchers = [[NSMutableArray alloc] init]; + NSPointerArray *uploadFetcherPointerArray = [self uploadFetcherPointerArrayForBackgroundSessions]; + + // Collect the background session upload fetchers that are still in memory. + @synchronized(uploadFetcherPointerArray) { + [uploadFetcherPointerArray compact]; + for (GTMSessionUploadFetcher *uploadFetcher in uploadFetcherPointerArray) { + NSString *sessionIdentifier = uploadFetcher.chunkFetcher.sessionIdentifier; + if (sessionIdentifier) { + [restoredSessionIdentifiers addObject:sessionIdentifier]; + [uploadFetchers addObject:uploadFetcher]; + } + } + } // @synchronized(uploadFetcherPointerArray) + + // The system may have other ongoing background upload sessions. Restore upload fetchers for those + // too. + NSArray *fetchers = [GTMSessionFetcher fetchersForBackgroundSessions]; + for (GTMSessionFetcher *fetcher in fetchers) { + NSString *sessionIdentifier = fetcher.sessionIdentifier; + if (!sessionIdentifier || [restoredSessionIdentifiers containsObject:sessionIdentifier]) { + continue; + } + NSDictionary *sessionIdentifierMetadata = [fetcher sessionIdentifierMetadata]; + if (sessionIdentifierMetadata == nil) { + continue; + } + if (![sessionIdentifierMetadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] boolValue]) { + continue; + } + GTMSessionUploadFetcher *uploadFetcher = + [self uploadFetcherForSessionIdentifierMetadata:sessionIdentifierMetadata]; + if (uploadFetcher == nil) { + // Something went wrong with this upload fetcher, so kill the restored chunk fetcher. + [fetcher stopFetching]; + continue; + } + [uploadFetchers addObject:uploadFetcher]; + uploadFetcher->_chunkFetcher = fetcher; + uploadFetcher->_fetcherInFlight = fetcher; + [uploadFetcher attachSendProgressBlockToChunkFetcher:fetcher]; + fetcher.completionHandler = + [fetcher completionHandlerWithTarget:uploadFetcher + didFinishSelector:@selector(chunkFetcher:finishedWithData:error:)]; + + GTMSESSION_LOG_DEBUG(@"%@ restoring upload fetcher %@ for chunk fetcher %@", + [self class], uploadFetcher, fetcher); + } + return uploadFetchers; +} + +- (void)setUploadData:(NSData *)data { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadData != data) { + _uploadData = data; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSData *)uploadData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadData; + } +} + +- (void)setUploadFileHandle:(NSFileHandle *)fh { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileHandle != fh) { + _uploadFileHandle = fh; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSFileHandle *)uploadFileHandle { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadFileHandle; + } +} + +- (void)setUploadFileURL:(NSURL *)uploadURL { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileURL != uploadURL) { + _uploadFileURL = uploadURL; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSURL *)uploadFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadFileURL; + } +} + +- (void)setUploadFileLength:(int64_t)fullLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileLength == kGTMSessionUploadFetcherUnknownFileSize && + fullLength != kGTMSessionUploadFetcherUnknownFileSize) { + _uploadFileLength = fullLength; + } + } +} + +- (void)setUploadDataLength:(int64_t)fullLength + provider:(GTMSessionUploadFetcherDataProvider)block { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadDataProvider = [block copy]; + _uploadFileLength = fullLength; + } + [self setupRequestHeaders]; +} + +- (GTMSessionUploadFetcherDataProvider)uploadDataProvider { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadDataProvider; + } +} + + +- (void)setUploadMIMEType:(NSString *)uploadMIMEType { + GTMSESSION_ASSERT_DEBUG(0, @"TODO: disallow setUploadMIMEType by making declaration readonly"); + // (and uploadMIMEType, chunksize, currentOffset) + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadMIMEType = uploadMIMEType; + } +} + +- (NSString *)uploadMIMEType { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadMIMEType; + } +} + +- (int64_t)chunkSize { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _chunkSize; + } +} + +- (void)setupRequestHeaders { + GTMSessionCheckNotSynchronized(self); + +#if DEBUG + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + int hasData = (_uploadData != nil) ? 1 : 0; + int hasFileHandle = (_uploadFileHandle != nil) ? 1 : 0; + int hasFileURL = (_uploadFileURL != nil) ? 1 : 0; + int hasUploadDataProvider = (_uploadDataProvider != nil) ? 1 : 0; + int numberOfSources = hasData + hasFileHandle + hasFileURL + hasUploadDataProvider; + #pragma unused(numberOfSources) + GTMSESSION_ASSERT_DEBUG(numberOfSources == 1, + @"Need just one upload source (%d)", numberOfSources); + } // @synchronized(self) +#endif + + // Add our custom headers to the initial request indicating the data + // type and total size to be delivered later in the chunk requests. + NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; + + GTMSESSION_ASSERT_DEBUG((mutableRequest == nil) != (_uploadLocationURL == nil), + @"Request and location are mutually exclusive"); + if (!mutableRequest) return; + + [mutableRequest setValue:kGTMSessionXGoogUploadProtocolResumable + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadProtocol]; + [mutableRequest setValue:@"start" + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + [mutableRequest setValue:_uploadMIMEType + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentType]; + [mutableRequest setValue:@([self fullUploadLength]).stringValue + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentLength]; + + NSString *method = mutableRequest.HTTPMethod; + if (method == nil || [method caseInsensitiveCompare:@"GET"] == NSOrderedSame) { + [mutableRequest setHTTPMethod:@"POST"]; + } + + // Ensure the user agent header identifies this to the upload server as a + // GTMSessionUploadFetcher client. The /1 can be incremented in the unlikely circumstance + // we need to make a bug fix in the client that the server can recognize. + NSString *const kUserAgentStub = @"(GTMSUF/1)"; + NSString *userAgent = [mutableRequest valueForHTTPHeaderField:@"User-Agent"]; + if (userAgent == nil + || [userAgent rangeOfString:kUserAgentStub].location == NSNotFound) { + if (userAgent.length == 0) { + userAgent = GTMFetcherStandardUserAgentString(nil); + } + userAgent = [userAgent stringByAppendingFormat:@" %@", kUserAgentStub]; + [mutableRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + [self setRequest:mutableRequest]; +} + +- (void)setLocationURL:(NSURL *GTM_NULLABLE_TYPE)location + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(chunkSize > 0, @"chunk size is zero"); + + _allowsCellularAccess = allowsCellularAccess; + + // When resuming an upload, set the known upload target URL. + _uploadLocationURL = location; + + _uploadMIMEType = uploadMIMEType; + _chunkSize = chunkSize; + + // Indicate that we've not yet determined the file handle's length + _uploadFileLength = kGTMSessionUploadFetcherUnknownFileSize; + + // Indicate that we've not yet determined the upload fetcher status + _recentChunkStatusCode = -1; + + // If this is restarting an upload begun by another fetcher, + // the location is specified but the request is nil + _isRestartedUpload = (location != nil); + } // @synchronized(self) +} + +- (int64_t)fullUploadLength { + int64_t result; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadData) { + result = (int64_t)_uploadData.length; + } else { + if (_uploadFileLength == kGTMSessionUploadFetcherUnknownFileSize) { + if (_uploadFileHandle) { + // First time through, seek to end to determine file length + _uploadFileLength = (int64_t)[_uploadFileHandle seekToEndOfFile]; + } else if (_uploadDataProvider) { + // _uploadFileLength is set when the _uploadDataProvider is set. + GTMSESSION_ASSERT_DEBUG(_uploadFileLength >= 0, @"No uploadDataProvider length set"); + } else { + NSNumber *filesizeNum; + NSError *valueError; + if ([_uploadFileURL getResourceValue:&filesizeNum + forKey:NSURLFileSizeKey + error:&valueError]) { + _uploadFileLength = filesizeNum.longLongValue; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Cannot get file size: %@\n %@", + valueError, _uploadFileURL.path); + _uploadFileLength = 0; + } + } + } + result = _uploadFileLength; + } + } // @synchronized(self) + return result; +} + +// Make a subdata of the upload data. +- (void)generateChunkSubdataWithOffset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + GTMSessionUploadFetcherDataProvider uploadDataProvider = self.uploadDataProvider; + if (uploadDataProvider) { + uploadDataProvider(offset, length, response); + return; + } + + NSData *uploadData = self.uploadData; + if (uploadData) { + // NSData provided. + NSData *resultData; + if (offset == 0 && length == (int64_t)uploadData.length) { + resultData = uploadData; + } else { + int64_t dataLength = (int64_t)uploadData.length; + // Ensure our range is valid. b/18007814 + if (offset + length > dataLength) { + NSString *errorMessage = [NSString stringWithFormat: + @"Range invalid for upload data. offset: %lld\tlength: %lld\tdataLength: %lld", + offset, length, dataLength]; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + NSRange range = NSMakeRange((NSUInteger)offset, (NSUInteger)length); + + @try { + resultData = [uploadData subdataWithRange:range]; + } + @catch (NSException *exception) { + NSString *errorMessage = exception.description; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + } + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, nil); + return; + } + NSURL *uploadFileURL = self.uploadFileURL; + if (uploadFileURL) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self generateChunkSubdataFromFileURL:uploadFileURL + offset:offset + length:length + response:response]; + }); + return; + } + GTMSESSION_ASSERT_DEBUG(_uploadFileHandle, @"Unexpectedly missing upload data package"); + NSFileHandle *uploadFileHandle = self.uploadFileHandle; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self generateChunkSubdataFromFileHandle:uploadFileHandle + offset:offset + length:length + response:response]; + }); +} + +- (void)generateChunkSubdataFromFileHandle:(NSFileHandle *)fileHandle + offset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + NSData *resultData; + NSError *error; + @try { + [fileHandle seekToFileOffset:(unsigned long long)offset]; + resultData = [fileHandle readDataOfLength:(NSUInteger)length]; + } + @catch (NSException *exception) { + GTMSESSION_ASSERT_DEBUG(NO, @"uploadFileHandle failed to read, %@", exception); + error = [self uploadChunkUnavailableErrorWithDescription:exception.description]; + } + // The response always re-dispatches to the main thread, so we skip doing that here. + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, error); +} + +- (void)generateChunkSubdataFromFileURL:(NSURL *)fileURL + offset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + GTMSessionCheckNotSynchronized(self); + + NSData *resultData; + NSError *error; + int64_t fullUploadLength = [self fullUploadLength]; + NSData *mappedData = + [NSData dataWithContentsOfURL:fileURL + options:NSDataReadingMappedAlways + NSDataReadingUncached + error:&error]; + if (!mappedData) { + // We could not create an NSData by memory-mapping the file. +#if TARGET_IPHONE_SIMULATOR + // NSTemporaryDirectory() can differ in the simulator between app restarts, + // yet the contents for the new path remains unchanged, so try the latest temp path. + if ([error.domain isEqual:NSCocoaErrorDomain] && (error.code == NSFileReadNoSuchFileError)) { + NSString *filename = [fileURL lastPathComponent]; + NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; + NSURL *newFileURL = [NSURL fileURLWithPath:filePath]; + if (![newFileURL isEqual:fileURL]) { + [self generateChunkSubdataFromFileURL:newFileURL + offset:offset + length:length + response:response]; + return; + } + } +#endif + + // If the file is just too large to create an NSData for, or if for some other reason we can't + // map it, create an NSFileHandle instead to read a subset into an NSData. +#if DEBUG + NSNumber *fileSizeNum; + BOOL hasFileSize = [fileURL getResourceValue:&fileSizeNum forKey:NSURLFileSizeKey error:NULL]; + GTMSESSION_LOG_DEBUG(@"Note: uploadFileURL is falling back to creating upload chunks by reading" + @" an NSFileHandle since uploadFileURL failed to map the upload file," + @" file size %@, %@", + hasFileSize ? fileSizeNum : @"unknown", error); +#endif + + NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:fileURL + error:&error]; + if (fileHandle != nil) { + [self generateChunkSubdataFromFileHandle:fileHandle + offset:offset + length:length + response:response]; + return; + } + GTMSESSION_ASSERT_DEBUG(NO, @"uploadFileURL failed to read, %@", error); + // Fall through with the error. + } else { + // Successfully created an NSData by memory-mapping the file. + if ((NSUInteger)(offset + length) > mappedData.length) { + NSString *errorMessage = [NSString stringWithFormat: + @"Range invalid for upload data. offset: %lld\tlength: %lld\tdataLength: %lld\texpected UploadLength: %lld", + offset, length, (long long)mappedData.length, fullUploadLength]; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + if (offset > 0 || length < fullUploadLength) { + NSRange range = NSMakeRange((NSUInteger)offset, (NSUInteger)length); + resultData = [mappedData subdataWithRange:range]; + } else { + resultData = mappedData; + } + } + // The response always re-dispatches to the main thread, so we skip re-dispatching here. + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, error); +} + +- (NSError *)uploadChunkUnavailableErrorWithDescription:(NSString *)description { + // The description in the userInfo is intended as a clue to programmers, not + // for client code to examine or rely on. + NSDictionary *userInfo = @{ @"description" : description }; + return [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorUploadChunkUnavailable + userInfo:userInfo]; +} + +- (NSError *)prematureFailureErrorWithUserInfo:(NSDictionary *)userInfo { + // An error for if we get an unexpected status from the upload server or + // otherwise cannot continue. This is an issue beyond the upload protocol; + // there's no way the client can do anything useful except give up. + NSError *error = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:501 // Not implemented + userInfo:userInfo]; + return error; +} + ++ (GTMSessionUploadFetcherStatus)uploadStatusFromResponseHeaders:(NSDictionary *)responseHeaders { + NSString *statusString = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus]; + if ([statusString isEqual:@"active"]) { + return kStatusActive; + } + if ([statusString isEqual:@"final"]) { + return kStatusFinal; + } + if ([statusString isEqual:@"cancelled"]) { + return kStatusCancelled; + } + return kStatusUnknown; +} + +#pragma mark Method overrides affecting the initial fetch only + +- (void)setCompletionHandler:(GTMSessionFetcherCompletionHandler)handler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCompletionHandler = handler; + } +} + +- (void)setDelegateCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCallbackQueue = queue; + } +} + +- (dispatch_queue_t GTM_NULLABLE_TYPE)delegateCallbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateCallbackQueue; + } +} + +- (BOOL)isRestartedUpload { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isRestartedUpload; + } +} + +- (GTMSessionFetcher * GTM_NULLABLE_TYPE)chunkFetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _chunkFetcher; + } +} + +- (void)setChunkFetcher:(GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _chunkFetcher = fetcher; + } +} + +- (void)setFetcherInFlight:(GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _fetcherInFlight = fetcher; + } +} + +- (GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcherInFlight { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _fetcherInFlight; + } +} + +- (void)setCancellationHandler:(GTMSessionUploadFetcherCancellationHandler GTM_NULLABLE_TYPE) + cancellationHandler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _cancellationHandler = cancellationHandler; + } +} + +- (GTMSessionUploadFetcherCancellationHandler GTM_NULLABLE_TYPE)cancellationHandler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _cancellationHandler; + } +} + +- (void)beginFetchForRetry { + GTMSessionCheckNotSynchronized(self); + + // Override the superclass to reset the initial body length and fetcher-in-flight, + // then call the superclass implementation. + [self setInitialBodyLength:[self bodyLength]]; + + GTMSESSION_ASSERT_DEBUG(self.fetcherInFlight == nil, @"unexpected fetcher in flight: %@", + self.fetcherInFlight); + self.fetcherInFlight = self; + [super beginFetchForRetry]; +} + +- (void)beginFetchWithCompletionHandler:(GTMSessionFetcherCompletionHandler)handler { + GTMSessionCheckNotSynchronized(self); + + [self setInitialBodyLength:[self bodyLength]]; + + // We'll hold onto the superclass's callback queue so we can invoke the handler + // even after the superclass has released the queue and its callback handler, as + // happens during auth failure. + [self setDelegateCallbackQueue:self.callbackQueue]; + self.completionHandler = handler; + + if ([self isRestartedUpload]) { + // When restarting an upload, we know the destination location for chunk fetches, + // but we need to query to find the initial offset. + if (![self isPaused]) { + [self sendQueryForUploadOffsetWithFetcherProperties:self.properties]; + } + return; + } + // We don't want to call into the client's completion block immediately + // after the finish of the initial connection (the delegate is called only + // when uploading finishes), so we substitute our own completion block to be + // called when the initial connection finishes + GTMSESSION_ASSERT_DEBUG(self.fetcherInFlight == nil, @"unexpected fetcher in flight: %@", + self.fetcherInFlight); + + self.fetcherInFlight = self; + [super beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + self.fetcherInFlight = nil; + // callback + + BOOL hasTestBlock = (self.testBlock != nil); + if (![self isRestartedUpload] && !hasTestBlock) { + if (error == nil) { + [self beginChunkFetches]; + } else { + if ([self retryTimer] == nil) { + [self invokeFinalCallbackWithData:nil + error:error + shouldInvalidateLocation:YES]; + } + } + } else { + // If there was no initial request, then this fetch is resuming some + // other uploadFetcher's initial request, and the superclass's connection + // is never used, so at this point we call the user's actual completion + // block. + if (!hasTestBlock) { + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + } else { + // There was a test block, so we won't do chunk fetches, but we simulate obtaining + // the data to be uploaded from the upload data provider block or the file handle, + // and then call back. + [self generateChunkSubdataWithOffset:0 + length:[self fullUploadLength] + response:^(NSData *generateData, int64_t fullUploadLength, NSError *generateError) { + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + }]; + } + } + }]; +} + +- (void)beginChunkFetches { + GTMSessionCheckNotSynchronized(self); + +#if DEBUG + // The initial response of the resumable upload protocol should have an + // empty body + // + // This assert typically happens because the upload create/edit link URL was + // not supplied with the request, and the server is thus expecting a non- + // resumable request/response. + if (self.downloadedData.length > 0) { + NSData *downloadedData = self.downloadedData; + NSString *str = [[NSString alloc] initWithData:downloadedData + encoding:NSUTF8StringEncoding]; + #pragma unused(str) + GTMSESSION_ASSERT_DEBUG(NO, @"unexpected response data (uploading to the wrong URL?)\n%@", str); + } +#endif + + // We need to get the upload URL from the location header to continue. + NSDictionary *responseHeaders = [self responseHeaders]; + + [self retrieveUploadChunkGranularityFromResponseHeaders:responseHeaders]; + + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown, + @"beginChunkFetches has unexpected upload status for headers %@", responseHeaders); + + BOOL isPrematureStop = (uploadStatus == kStatusFinal) || (uploadStatus == kStatusCancelled); + + NSString *uploadLocationURLStr = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadURL]; + BOOL hasUploadLocation = (uploadLocationURLStr.length > 0); + + if (isPrematureStop || !hasUploadLocation) { + GTMSESSION_ASSERT_DEBUG(NO, @"Premature failure: upload-status:\"%@\" location:%@", + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus], uploadLocationURLStr); + // We cannot continue since we do not know the location to use + // as our upload destination. + NSDictionary *userInfo = nil; + NSData *downloadedData = self.downloadedData; + if (downloadedData.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : downloadedData }; + } + NSError *failureError = [self prematureFailureErrorWithUserInfo:userInfo]; + [self invokeFinalCallbackWithData:nil + error:failureError + shouldInvalidateLocation:YES]; + return; + } + + self.uploadLocationURL = [NSURL URLWithString:uploadLocationURLStr]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMSessionFetcherUploadLocationObtainedNotification + object:self]; + + // we've now sent all of the initial post body data, so we need to include + // its size in future progress indicator callbacks + [self setInitialBodySent:[self initialBodyLength]]; + + // just in case the user paused us during the initial fetch... + if (![self isPaused]) { + [self uploadNextChunkWithOffset:0]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent + totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + // Overrides the superclass. + [self invokeDelegateWithDidSendBytes:bytesSent + totalBytesSent:totalBytesSent + totalBytesExpectedToSend:totalBytesExpectedToSend + [self fullUploadLength]]; +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // Overrides the superclass. + + // We don't want the superclass to release the delegate and callback + // blocks once the initial fetch has finished + // + // This is invoked for only successful completion of the connection; + // an error always will invoke and release the callbacks + return NO; +} + +- (void)invokeFinalCallbackWithData:(NSData *)data + error:(NSError *)error + shouldInvalidateLocation:(BOOL)shouldInvalidateLocation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (shouldInvalidateLocation) { + _uploadLocationURL = nil; + } + + dispatch_queue_t queue = _delegateCallbackQueue; + GTMSessionFetcherCompletionHandler handler = _delegateCompletionHandler; + if (queue && handler) { + [self invokeOnCallbackQueue:queue + afterUserStopped:NO + block:^{ + handler(data, error); + }]; + } + } // @synchronized(self) + + [self releaseUploadAndBaseCallbacks:!self.userStoppedFetching]; +} + +- (void)releaseUploadAndBaseCallbacks:(BOOL)shouldReleaseCancellation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCallbackQueue = nil; + _delegateCompletionHandler = nil; + _uploadDataProvider = nil; + if (shouldReleaseCancellation) { + _cancellationHandler = nil; + } + } + + // Release the base class's callbacks, too, if needed. + [self releaseCallbacks]; +} + +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks { + GTMSessionCheckNotSynchronized(self); + + // Clear _fetcherInFlight when stopped. Moved from stopFetching, since that's a public method, + // where this method does the work. Fixes issue clearing value when retryBlock included. + GTMSessionFetcher *fetcherInFlight = self.fetcherInFlight; + if (fetcherInFlight == self) { + self.fetcherInFlight = nil; + } + + [super stopFetchReleasingCallbacks:shouldReleaseCallbacks]; + + if (shouldReleaseCallbacks) { + [self releaseUploadAndBaseCallbacks:NO]; + } +} + +#pragma mark Chunk fetching methods + +- (void)uploadNextChunkWithOffset:(int64_t)offset { + // use the properties in each chunk fetcher + NSDictionary *props = [self properties]; + + [self uploadNextChunkWithOffset:offset + fetcherProperties:props]; +} + +- (void)sendQueryForUploadOffsetWithFetcherProperties:(NSDictionary *)props { + GTMSessionFetcher *queryFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:YES]; + queryFetcher.bodyData = [NSData data]; + + NSString *originalComment = self.comment; + [queryFetcher setCommentWithFormat:@"%@ (query offset)", + originalComment ? originalComment : @"upload"]; + + [queryFetcher setRequestValue:@"query" forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + + self.fetcherInFlight = queryFetcher; + [queryFetcher beginFetchWithDelegate:self + didFinishSelector:@selector(queryFetcher:finishedWithData:error:)]; +} + +- (void)queryFetcher:(GTMSessionFetcher *)queryFetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + self.fetcherInFlight = nil; + + NSDictionary *responseHeaders = [queryFetcher responseHeaders]; + NSString *sizeReceivedHeader; + + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown || error != nil, + @"query fetcher completion has unexpected upload status for headers %@", responseHeaders); + + if (error == nil) { + sizeReceivedHeader = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadSizeReceived]; + + if (uploadStatus == kStatusCancelled || + (uploadStatus == kStatusActive && sizeReceivedHeader == nil)) { + NSDictionary *userInfo = nil; + if (data.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : data }; + } + error = [self prematureFailureErrorWithUserInfo:userInfo]; + } + } + + if (error == nil) { + int64_t offset = [sizeReceivedHeader longLongValue]; + int64_t fullUploadLength = [self fullUploadLength]; + if (uploadStatus == kStatusFinal || + (offset >= fullUploadLength && + fullUploadLength != kGTMSessionUploadFetcherUnknownFileSize)) { + // Handle we're done + [self chunkFetcher:queryFetcher finishedWithData:data error:nil]; + } else { + [self retrieveUploadChunkGranularityFromResponseHeaders:responseHeaders]; + [self uploadNextChunkWithOffset:offset]; + } + } else { + // Handle query error + [self chunkFetcher:queryFetcher finishedWithData:data error:error]; + } +} + +- (void)sendCancelUploadWithFetcherProperties:(NSDictionary *)props { + @synchronized(self) { + _isCancelInFlight = YES; + } + GTMSessionFetcher *cancelFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:YES]; + cancelFetcher.bodyData = [NSData data]; + + NSString *originalComment = self.comment; + [cancelFetcher setCommentWithFormat:@"%@ (cancel)", + originalComment ? originalComment : @"upload"]; + + [cancelFetcher setRequestValue:@"cancel" forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + + self.fetcherInFlight = cancelFetcher; + [cancelFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + self.fetcherInFlight = nil; + if (![self triggerCancellationHandlerForFetch:cancelFetcher data:data error:error]) { + if (error) { + GTMSESSION_LOG_DEBUG(@"cancelFetcher %@", error); + } + } + @synchronized(self) { + self->_isCancelInFlight = NO; + } + }]; +} + +- (void)uploadNextChunkWithOffset:(int64_t)offset + fetcherProperties:(NSDictionary *)props { + GTMSessionCheckNotSynchronized(self); + + // Example chunk headers: + // X-Goog-Upload-Command: upload, finalize + // X-Goog-Upload-Offset: 0 + // Content-Length: 2000000 + // Content-Type: image/jpeg + // + // {bytes 0-1999999} + + // The chunk upload URL requires no authentication header. + GTMSessionFetcher *chunkFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:NO]; + [self attachSendProgressBlockToChunkFetcher:chunkFetcher]; + int64_t chunkSize = [self updateChunkFetcher:chunkFetcher + forChunkAtOffset:offset]; + BOOL isUploadingFileURL = (self.uploadFileURL != nil); + int64_t fullUploadLength = [self fullUploadLength]; + + // The chunk size may have changed, so determine again if we're uploading the full file. + BOOL isUploadingFullFile = (offset == 0 && + fullUploadLength != kGTMSessionUploadFetcherUnknownFileSize && + chunkSize >= fullUploadLength); + if (isUploadingFullFile && isUploadingFileURL) { + // The data is the full upload file URL. + chunkFetcher.bodyFileURL = self.uploadFileURL; + [self beginChunkFetcher:chunkFetcher + offset:offset]; + } else { + // Make an NSData for the subset for this upload chunk. + self.subdataGenerating = YES; + [self generateChunkSubdataWithOffset:offset + length:chunkSize + response:^(NSData *chunkData, int64_t uploadFileLength, NSError *chunkError) { + // The subdata methods may leave us on a background thread. + dispatch_async(dispatch_get_main_queue(), ^{ + self.subdataGenerating = NO; + + // dont allow the updating of fileLength for uploads not using a data provider as they + // should know the file length before the upload starts. + if (self->_uploadDataProvider != nil && uploadFileLength > 0) { + [self setUploadFileLength:uploadFileLength]; + // Update the command and content-length headers if this is the last chunk to be sent. + if (offset + chunkSize >= uploadFileLength) { + int64_t updatedChunkSize = [self updateChunkFetcher:chunkFetcher + forChunkAtOffset:offset]; + if (updatedChunkSize == 0) { + // Calling beginChunkFetcher early when there is no more data to send allows us to + // properly handle nil chunkData below without having to account for the case where + // we are just finalizing the file. + chunkFetcher.bodyData = [[NSData alloc] init]; + [self beginChunkFetcher:chunkFetcher + offset:offset]; + return; + } + } + } + + if (chunkData == nil) { + NSError *responseError = chunkError; + if (!responseError) { + responseError = [self uploadChunkUnavailableErrorWithDescription:@"chunkData is nil"]; + } + [self invokeFinalCallbackWithData:nil + error:responseError + shouldInvalidateLocation:YES]; + return; + } + + BOOL didWriteFile = NO; + if (isUploadingFileURL) { + // Make a temporary file with the data subset. + NSString *tempName = + [NSString stringWithFormat:@"GTMUpload_temp_%@", [[NSUUID UUID] UUIDString]]; + NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:tempName]; + NSError *writeError; + didWriteFile = [chunkData writeToFile:tempPath + options:NSDataWritingAtomic + error:&writeError]; + if (didWriteFile) { + chunkFetcher.bodyFileURL = [NSURL fileURLWithPath:tempPath]; + } else { + GTMSESSION_LOG_DEBUG(@"writeToFile failed: %@\n%@", writeError, tempPath); + } + } + if (!didWriteFile) { + chunkFetcher.bodyData = [chunkData copy]; + } + [self beginChunkFetcher:chunkFetcher + offset:offset]; + }); + }]; + } +} + +- (void)beginChunkFetcher:(GTMSessionFetcher *)chunkFetcher + offset:(int64_t)offset { + + // Track the current offset for progress reporting + self.currentOffset = offset; + + // Hang on to the fetcher in case we need to cancel it. We set these before beginning the + // chunk fetch so the observers notified of chunk fetches can inspect the upload fetcher to + // match to the chunk. + self.chunkFetcher = chunkFetcher; + self.fetcherInFlight = chunkFetcher; + + // Update the last chunk request, including any request headers. + self.lastChunkRequest = chunkFetcher.request; + + [chunkFetcher beginFetchWithDelegate:self + didFinishSelector:@selector(chunkFetcher:finishedWithData:error:)]; +} + +- (void)attachSendProgressBlockToChunkFetcher:(GTMSessionFetcher *)chunkFetcher { + chunkFetcher.sendProgressBlock = ^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + // The total bytes expected include the initial body and the full chunked + // data, independent of how big this fetcher's chunk is. + int64_t initialBodySent = [self bodyLength]; // TODO(grobbins) use [self initialBodySent] + int64_t totalSent = initialBodySent + self.currentOffset + totalBytesSent; + int64_t totalExpected = initialBodySent + [self fullUploadLength]; + + [self invokeDelegateWithDidSendBytes:bytesSent + totalBytesSent:totalSent + totalBytesExpectedToSend:totalExpected]; + }; +} + +- (NSDictionary *)uploadSessionIdentifierMetadata { + NSMutableDictionary *metadata = [NSMutableDictionary dictionary]; + metadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] = @YES; + GTMSESSION_ASSERT_DEBUG(self.uploadFileURL, + @"Invalid upload fetcher to create session identifier for metadata"); + metadata[kGTMSessionIdentifierUploadFileURLMetadataKey] = [self.uploadFileURL absoluteString]; + metadata[kGTMSessionIdentifierUploadFileLengthMetadataKey] = @([self fullUploadLength]); + + if (self.uploadLocationURL) { + metadata[kGTMSessionIdentifierUploadLocationURLMetadataKey] = + [self.uploadLocationURL absoluteString]; + } + if (self.uploadMIMEType) { + metadata[kGTMSessionIdentifierUploadMIMETypeMetadataKey] = self.uploadMIMEType; + } + metadata[kGTMSessionIdentifierUploadChunkSizeMetadataKey] = @(self.chunkSize); + metadata[kGTMSessionIdentifierUploadCurrentOffsetMetadataKey] = @(self.currentOffset); + metadata[kGTMSessionIdentifierUploadAllowsCellularAccess] = @(self.request.allowsCellularAccess); + + return metadata; +} + +- (GTMSessionFetcher *)uploadFetcherWithProperties:(NSDictionary *)properties + isQueryFetch:(BOOL)isQueryFetch { + GTMSessionCheckNotSynchronized(self); + + // Common code to make a request for a query command or for a chunk upload. + NSURL *uploadLocationURL = self.uploadLocationURL; + NSMutableURLRequest *chunkRequest = [NSMutableURLRequest requestWithURL:uploadLocationURL]; + [chunkRequest setHTTPMethod:@"PUT"]; + + // copy the user-agent from the original connection + // n.b. that self.request is nil for upload fetchers created with an existing upload location + // URL. + NSURLRequest *origRequest = self.request; + + chunkRequest.allowsCellularAccess = origRequest.allowsCellularAccess; + if (!origRequest) { + chunkRequest.allowsCellularAccess = _allowsCellularAccess; + } + NSString *userAgent = [origRequest valueForHTTPHeaderField:@"User-Agent"]; + if (userAgent.length > 0) { + [chunkRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + + [chunkRequest setValue:kGTMSessionXGoogUploadProtocolResumable + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadProtocol]; + + // To avoid timeouts when debugging, copy the timeout of the initial fetcher. + NSTimeInterval origTimeout = [origRequest timeoutInterval]; + [chunkRequest setTimeoutInterval:origTimeout]; + + // + // Make a new chunk fetcher. + // + GTMSessionFetcher *chunkFetcher = [GTMSessionFetcher fetcherWithRequest:chunkRequest]; + chunkFetcher.callbackQueue = self.callbackQueue; + chunkFetcher.sessionUserInfo = self.sessionUserInfo; + chunkFetcher.configurationBlock = self.configurationBlock; + chunkFetcher.allowedInsecureSchemes = self.allowedInsecureSchemes; + chunkFetcher.allowLocalhostRequest = self.allowLocalhostRequest; + chunkFetcher.allowInvalidServerCertificates = self.allowInvalidServerCertificates; + chunkFetcher.useUploadTask = !isQueryFetch; + + if (self.uploadFileURL && !isQueryFetch && self.useBackgroundSession) { + [chunkFetcher createSessionIdentifierWithMetadata:[self uploadSessionIdentifierMetadata]]; + } + + // Give the chunk fetcher the same properties as the previous chunk fetcher + chunkFetcher.properties = [properties mutableCopy]; + [chunkFetcher setProperty:[NSValue valueWithNonretainedObject:self] + forKey:kGTMSessionUploadFetcherChunkParentKey]; + + // copy other fetcher settings to the new fetcher + chunkFetcher.retryEnabled = self.retryEnabled; + chunkFetcher.maxRetryInterval = self.maxRetryInterval; + + if ([self isRetryEnabled]) { + // We interpose our own retry method both so we can change the request to ask the server to + // tell us where to resume the chunk. + chunkFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *chunkError, + GTMSessionFetcherRetryResponse response) { + void (^finish)(BOOL) = ^(BOOL shouldRetry){ + // We'll retry by sending an offset query. + if (shouldRetry) { + self.shouldInitiateOffsetQuery = !isQueryFetch; + + // We don't know what our actual offset is anymore, but the server will tell us. + self.currentOffset = 0; + } + // We don't actually want to retry this specific fetcher. + response(NO); + }; + + GTMSessionFetcherRetryBlock retryBlock = self.retryBlock; + if (retryBlock) { + // Ask the client, then call the finish block above. + retryBlock(suggestedWillRetry, chunkError, finish); + } else { + finish(suggestedWillRetry); + } + }; + } + + return chunkFetcher; +} + +- (void)chunkFetcher:(GTMSessionFetcher *)chunkFetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + BOOL hasDestroyedOldChunkFetcher = NO; + self.fetcherInFlight = nil; + + NSDictionary *responseHeaders = [chunkFetcher responseHeaders]; + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown + || error != nil + || self.wasCreatedFromBackgroundSession, + @"chunk fetcher completion has kStatusUnknown upload status for headers %@ fetcher %@", + responseHeaders, self); + BOOL isUploadStatusStopped = (uploadStatus == kStatusFinal || uploadStatus == kStatusCancelled); + + // Check if the fetcher was actually querying. If it failed, do not retry, + // as it would enter an infinite retry loop. + NSString *uploadCommand = + chunkFetcher.request.allHTTPHeaderFields[kGTMSessionHeaderXGoogUploadCommand]; + BOOL isQueryFetch = [uploadCommand isEqual:@"query"]; + + // TODO + // Maybe here we can check to see if the request had x goog content length set. (the file length one). + NSString *previousContentLengthValue = + [chunkFetcher.request valueForHTTPHeaderField:@"Content-Length"]; + // The Content-Length header may not be present if the chunk fetcher was recreated from + // a background session. + BOOL hasKnownChunkSize = (previousContentLengthValue != nil); + int64_t previousContentLength = [previousContentLengthValue longLongValue]; + + BOOL needsQuery = (!hasKnownChunkSize && !isUploadStatusStopped); + + if (error || (needsQuery && !isQueryFetch)) { + NSInteger status = error.code; + + // Status 4xx indicates a bad offset in the Google upload protocol. However, do not retry status + // 404 per spec, nor if the upload size appears to have been zero (since the server will just + // keep asking us to retry.) + if (self.shouldInitiateOffsetQuery || + (needsQuery && !isQueryFetch) || + ([error.domain isEqual:kGTMSessionFetcherStatusDomain] && + status >= 400 && status <= 499 && + status != 404 && + uploadStatus == kStatusActive && + previousContentLength > 0)) { + self.shouldInitiateOffsetQuery = NO; + [self destroyChunkFetcher]; + hasDestroyedOldChunkFetcher = YES; + [self sendQueryForUploadOffsetWithFetcherProperties:chunkFetcher.properties]; + } else { + // Some unexpected status has occurred; handle it as we would a regular + // object fetcher failure. + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:NO]; + } + } else { + // The chunk has uploaded successfully. + int64_t newOffset = self.currentOffset + previousContentLength; +#if DEBUG + // Verify that if we think all of the uploading data has been sent, the server responded with + // the "final" upload status. + BOOL hasUploadAllData = (newOffset == [self fullUploadLength]); + BOOL isFinalStatus = (uploadStatus == kStatusFinal); + #pragma unused(hasUploadAllData,isFinalStatus) + GTMSESSION_ASSERT_DEBUG(hasUploadAllData == isFinalStatus || !hasKnownChunkSize, + @"uploadStatus:%@ newOffset:%lld (%lld + %lld) fullUploadLength:%lld" + @" chunkFetcher:%@ requestHeaders:%@ responseHeaders:%@", + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus], + newOffset, self.currentOffset, previousContentLength, + [self fullUploadLength], + chunkFetcher, chunkFetcher.request.allHTTPHeaderFields, + responseHeaders); +#endif + if (isUploadStatusStopped || + (!_uploadData && _uploadFileLength == 0) || + (_currentOffset > _uploadFileLength && _uploadFileLength > 0)) { + // This was the last chunk. + if (error == nil && uploadStatus == kStatusCancelled) { + // Report cancelled status as an error. + NSDictionary *userInfo = nil; + if (data.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : data }; + } + data = nil; + error = [self prematureFailureErrorWithUserInfo:userInfo]; + } else { + // The upload is in final status. + // + // Take the chunk fetcher's data as the superclass data. + self.downloadedData = data; + self.statusCode = chunkFetcher.statusCode; + } + + // we're done + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + } else { + // Start the next chunk. + self.currentOffset = newOffset; + + // We want to destroy this chunk fetcher before creating the next one, but + // we want to pass on its properties + NSDictionary *props = [chunkFetcher properties]; + + // We no longer need to be able to cancel this chunkFetcher. Destroy it + // before we create a new chunk fetcher. + [self destroyChunkFetcher]; + hasDestroyedOldChunkFetcher = YES; + + [self uploadNextChunkWithOffset:newOffset + fetcherProperties:props]; + } + } + if (!hasDestroyedOldChunkFetcher) { + [self destroyChunkFetcher]; + } +} + +- (void)destroyChunkFetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_fetcherInFlight == _chunkFetcher) { + _fetcherInFlight = nil; + } + + [_chunkFetcher stopFetching]; + + NSURL *chunkFileURL = _chunkFetcher.bodyFileURL; + BOOL wasTemporaryUploadFile = ![chunkFileURL isEqual:_uploadFileURL]; + if (wasTemporaryUploadFile) { + NSError *error; + [[NSFileManager defaultManager] removeItemAtURL:chunkFileURL + error:&error]; + if (error) { + GTMSESSION_LOG_DEBUG(@"removingItemAtURL failed: %@\n%@", error, chunkFileURL); + } + } + + _recentChunkReponseHeaders = _chunkFetcher.responseHeaders; + + // To avoid retain cycles, remove all properties except the parent identifier. + _chunkFetcher.properties = + @{ kGTMSessionUploadFetcherChunkParentKey : [NSValue valueWithNonretainedObject:self] }; + + _chunkFetcher.retryBlock = nil; + _chunkFetcher.sendProgressBlock = nil; + _chunkFetcher = nil; + } // @synchronized(self) +} + +// This method calculates the proper values to pass to the client's send progress block. +// +// The actual total bytes sent include the initial body sent, plus the +// offset into the batched data prior to the current chunk fetcher + +- (void)invokeDelegateWithDidSendBytes:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent + totalBytesExpectedToSend:(int64_t)totalBytesExpected { + GTMSessionCheckNotSynchronized(self); + + // Ensure the chunk fetcher survives the callback in case the user pauses the upload process. + __block GTMSessionFetcher *holdFetcher = self.chunkFetcher; + + [self invokeOnCallbackQueue:self.delegateCallbackQueue + afterUserStopped:NO + block:^{ + GTMSessionFetcherSendProgressBlock sendProgressBlock = self.sendProgressBlock; + if (sendProgressBlock) { + sendProgressBlock(bytesSent, totalBytesSent, totalBytesExpected); + } + holdFetcher = nil; + }]; +} + +- (void)retrieveUploadChunkGranularityFromResponseHeaders:(NSDictionary *)responseHeaders { + GTMSessionCheckNotSynchronized(self); + + // Standard granularity for Google uploads is 256K. + NSString *chunkGranularityHeader = + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadChunkGranularity]; + self.uploadGranularity = chunkGranularityHeader.longLongValue; +} + +#pragma mark - + +- (BOOL)isPaused { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isPaused; + } // @synchronized(self) +} + +- (void)pauseFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _isPaused = YES; + } // @synchronized(self) + + // Pausing just means stopping the current chunk from uploading; + // when we resume, we will send a query request to the server to + // figure out what bytes to resume sending. + // + // We won't try to cancel the initial data upload, but rather will check + // for being paused in beginChunkFetches. + [self destroyChunkFetcher]; +} + +- (void)resumeFetching { + BOOL wasPaused; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + wasPaused = _isPaused; + _isPaused = NO; + } // @synchronized(self) + + if (wasPaused) { + [self sendQueryForUploadOffsetWithFetcherProperties:self.properties]; + } +} + +- (void)stopFetching { + // Overrides the superclass + [self destroyChunkFetcher]; + + // If we think the server is waiting for more data, then tell it there won't be more. + if (self.uploadLocationURL) { + [self sendCancelUploadWithFetcherProperties:[self properties]]; + self.uploadLocationURL = nil; + } else { + [self invokeOnCallbackQueue:self.callbackQueue + afterUserStopped:YES + block:^{ + // Repeated calls to stopFetching may cause this path to be reached despite having sent a real + // cancel request, check here to ensure that the cancellation handler invocation which fires + // will definitely be for the real request sent previously. + @synchronized(self) { + if (self->_isCancelInFlight) { + return; + } + } + [self triggerCancellationHandlerForFetch:nil data:nil error:nil]; + }]; + } + + [super stopFetching]; +} + +// Fires the cancellation handler, returning whether there was a handler to be fired. +- (BOOL)triggerCancellationHandlerForFetch:(GTMSessionFetcher *)fetcher + data:(NSData *)data + error:(NSError *)error { + GTMSessionUploadFetcherCancellationHandler handler = self.cancellationHandler; + if (handler) { + handler(fetcher, data, error); + self.cancellationHandler = nil; + return YES; + } + return NO; +} + +#pragma mark - + +- (int64_t)updateChunkFetcher:(GTMSessionFetcher *)chunkFetcher + forChunkAtOffset:(int64_t)offset { + BOOL isUploadingFileURL = (self.uploadFileURL != nil); + + // Upload another chunk, meeting server-required granularity. + int64_t chunkSize = self.chunkSize; + + int64_t fullUploadLength = [self fullUploadLength]; + BOOL isFileLengthKnown = fullUploadLength >= 0; + + BOOL isUploadingFullFile = (offset == 0 && isFileLengthKnown && chunkSize >= fullUploadLength); + if (!isUploadingFileURL || !isUploadingFullFile) { + // We're not uploading the entire file and given the file URL. Since we'll be + // allocating a subdata block for a chunk, we need to bound it to something that + // won't blow the process's memory. + if (chunkSize > kGTMSessionUploadFetcherMaximumDemandBufferSize) { + chunkSize = kGTMSessionUploadFetcherMaximumDemandBufferSize; + } + } + + int64_t granularity = self.uploadGranularity; + if (granularity > 0) { + if (chunkSize < granularity) { + chunkSize = granularity; + } else { + chunkSize = chunkSize - (chunkSize % granularity); + } + } + + GTMSESSION_ASSERT_DEBUG(offset < fullUploadLength || fullUploadLength == 0, + @"offset %lld exceeds data length %lld", offset, fullUploadLength); + + if (granularity > 0) { + offset = offset - (offset % granularity); + } + + // If the chunk size is bigger than the remaining data, or else + // it's close enough in size to the remaining data that we'd rather + // avoid having a whole extra http fetch for the leftover bit, then make + // this chunk size exactly match the remaining data size + NSString *command; + int64_t thisChunkSize = chunkSize; + + BOOL isChunkTooBig = (thisChunkSize >= (fullUploadLength - offset)); + BOOL isChunkAlmostBigEnough = (fullUploadLength - offset - 2500 < thisChunkSize); + BOOL isFinalChunk = (isChunkTooBig || isChunkAlmostBigEnough) && isFileLengthKnown; + if (isFinalChunk) { + thisChunkSize = fullUploadLength - offset; + if (thisChunkSize > 0) { + command = @"upload, finalize"; + } else { + command = @"finalize"; + } + } else { + command = @"upload"; + } + NSString *lengthStr = @(thisChunkSize).stringValue; + NSString *offsetStr = @(offset).stringValue; + + [chunkFetcher setRequestValue:command forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + [chunkFetcher setRequestValue:lengthStr forHTTPHeaderField:@"Content-Length"]; + [chunkFetcher setRequestValue:offsetStr forHTTPHeaderField:kGTMSessionHeaderXGoogUploadOffset]; + if (_uploadFileLength != kGTMSessionUploadFetcherUnknownFileSize) { + [chunkFetcher setRequestValue:@([self fullUploadLength]).stringValue + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentLength]; + } + + // Append the range of bytes in this chunk to the fetcher comment. + NSString *baseComment = self.comment; + [chunkFetcher setCommentWithFormat:@"%@ (%lld-%lld)", + baseComment ? baseComment : @"upload", offset, MAX(0, offset + thisChunkSize - 1)]; + + return thisChunkSize; +} + +// Public properties. +@synthesize currentOffset = _currentOffset, + allowsCellularAccess = _allowsCellularAccess, + delegateCompletionHandler = _delegateCompletionHandler, + chunkFetcher = _chunkFetcher, + lastChunkRequest = _lastChunkRequest, + subdataGenerating = _subdataGenerating, + shouldInitiateOffsetQuery = _shouldInitiateOffsetQuery, + uploadGranularity = _uploadGranularity; + +// Internal properties. +@dynamic fetcherInFlight; +@dynamic activeFetcher; +@dynamic statusCode; +@dynamic delegateCallbackQueue; + ++ (void)removePointer:(void *)pointer fromPointerArray:(NSPointerArray *)pointerArray { + for (NSUInteger index = 0, count = pointerArray.count; index < count; ++index) { + void *pointerAtIndex = [pointerArray pointerAtIndex:index]; + if (pointerAtIndex == pointer) { + [pointerArray removePointerAtIndex:index]; + return; + } + } +} + +- (BOOL)useBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _useBackgroundSessionOnChunkFetchers; + } // @synchronized(self +} + +- (void)setUseBackgroundSession:(BOOL)useBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_useBackgroundSessionOnChunkFetchers != useBackgroundSession) { + _useBackgroundSessionOnChunkFetchers = useBackgroundSession; + NSPointerArray *uploadFetcherPointerArrayForBackgroundSessions = + [[self class] uploadFetcherPointerArrayForBackgroundSessions]; + @synchronized(uploadFetcherPointerArrayForBackgroundSessions) { + if (_useBackgroundSessionOnChunkFetchers) { + [uploadFetcherPointerArrayForBackgroundSessions addPointer:(__bridge void *)self]; + } else { + [[self class] removePointer:(__bridge void *)self + fromPointerArray:uploadFetcherPointerArrayForBackgroundSessions]; + } + } // @synchronized(uploadFetcherPointerArrayForBackgroundSessions) + } + } // @synchronized(self) +} + +- (BOOL)canFetchWithBackgroundSession { + // The initial upload fetcher is always a foreground session; the + // useBackgroundSession property will apply only to chunk fetchers, + // not to queries. + return NO; +} + +- (NSDictionary *)responseHeaders { + GTMSessionCheckNotSynchronized(self); + // Overrides the superclass + + // If asked for the fetcher's response, use the most recent chunk fetcher's response, + // since the original request's response lacks useful information like the actual + // Content-Type. + NSDictionary *dict = self.chunkFetcher.responseHeaders; + if (dict) { + return dict; + } + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_recentChunkReponseHeaders) { + return _recentChunkReponseHeaders; + } + } // @synchronized(self + + // No chunk fetcher yet completed, so return whatever we have from the initial fetch. + return [super responseHeaders]; +} + +- (NSInteger)statusCodeUnsynchronized { + GTMSessionCheckSynchronized(self); + + if (_recentChunkStatusCode != -1) { + // Overrides the superclass to indicate status appropriate to the initial + // or latest chunk fetch + return _recentChunkStatusCode; + } else { + return [super statusCodeUnsynchronized]; + } +} + + +- (void)setStatusCode:(NSInteger)val { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _recentChunkStatusCode = val; + } +} + +- (int64_t)initialBodyLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _initialBodyLength; + } +} + +- (void)setInitialBodyLength:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _initialBodyLength = length; + } +} + +- (int64_t)initialBodySent { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _initialBodySent; + } +} + +- (void)setInitialBodySent:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _initialBodySent = length; + } +} + +- (NSURL *)uploadLocationURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadLocationURL; + } +} + +- (void)setUploadLocationURL:(NSURL *)locationURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadLocationURL = locationURL; + } +} + +- (GTMSessionFetcher *)activeFetcher { + GTMSessionFetcher *result = self.fetcherInFlight; + if (result) return result; + + return self; +} + +- (BOOL)isFetching { + // If there is an active chunk fetcher, then the upload fetcher is considered + // to still be fetching. + if (self.fetcherInFlight != nil) return YES; + + return [super isFetching]; +} + +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + while (self.fetcherInFlight || self.subdataGenerating) { + if ([timeoutDate timeIntervalSinceNow] < 0) return NO; + + if (self.subdataGenerating) { + // Allow time for subdata generation. + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + // Wait for any chunk or query fetchers that still have pending callbacks or + // notifications. + BOOL timedOut; + + if (self.fetcherInFlight == self) { + timedOut = ![super waitForCompletionWithTimeout:timeoutInSeconds]; + } else { + timedOut = ![self.fetcherInFlight waitForCompletionWithTimeout:timeoutInSeconds]; + } + if (timedOut) return NO; + } + } + return YES; +} + +@end + +@implementation GTMSessionFetcher (GTMSessionUploadFetcherMethods) + +- (GTMSessionUploadFetcher *)parentUploadFetcher { + NSValue *property = [self propertyForKey:kGTMSessionUploadFetcherChunkParentKey]; + if (!property) return nil; + + GTMSessionUploadFetcher *uploadFetcher = property.nonretainedObjectValue; + + GTMSESSION_ASSERT_DEBUG([uploadFetcher isKindOfClass:[GTMSessionUploadFetcher class]], + @"Unexpected parent upload fetcher class: %@", [uploadFetcher class]); + return uploadFetcher; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement new file mode 100755 index 00000000..683f4f0d Binary files /dev/null and b/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap b/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap new file mode 100755 index 00000000..de80e9ea --- /dev/null +++ b/MyExperiences copy/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module GoogleAppMeasurement { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m new file mode 100644 index 00000000..3e5f57b5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORAssert.h" + +GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) { + // This class is only compiled in by unit tests, and this should fail quickly in optimized builds. + Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper"); + if (__builtin_expect(!!GDTCORAssertClass, 0)) { + SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock"); + if (assertionBlockSEL) { + IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL]; + if (assertionBlockIMP) { + GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)( + GDTCORAssertClass, assertionBlockSEL); + if (assertionBlock) { + return assertionBlock; + } + } + } + } + return NULL; +} diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m new file mode 100644 index 00000000..f0ea8ab6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m @@ -0,0 +1,164 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORClock.h" + +#import + +// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all +// are subject to drift. That it to say, multiple consecutive calls do not always result in a +// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external +// factors. This class attempts to determine the wall-clock time at the time of the event by +// capturing the kernel start and time since boot to determine a wallclock time in UTC. +// +// Timezone offsets at the time of a snapshot are also captured in order to provide local-time +// details. Other classes in this library depend on comparing times at some time in the future to +// a time captured in the past, and this class needs to provide a mechanism to do that. +// +// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide +// a monotonic clock mechanism to accurately check if some clock snapshot was before or after +// by using a shared reference point (kernel boot time). +// +// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be +// difficult to unit test. + +/** Returns the kernel boottime property from sysctl. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The KERN_BOOTTIME property from sysctl, in nanoseconds. + */ +static int64_t KernelBootTimeInNanoseconds() { + // Caching the result is not possible because clock drift would not be accounted for. + struct timeval boottime; + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + size_t size = sizeof(boottime); + int rc = sysctl(mib, 2, &boottime, &size, NULL, 0); + if (rc != 0) { + return 0; + } + return (int64_t)boottime.tv_sec * NSEC_PER_MSEC + (int64_t)boottime.tv_usec; +} + +/** Returns value of gettimeofday, in nanoseconds. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The value of gettimeofday, in nanoseconds. + */ +static int64_t UptimeInNanoseconds() { + int64_t before_now; + int64_t after_now; + struct timeval now; + + before_now = KernelBootTimeInNanoseconds(); + // Addresses a race condition in which the system time has updated, but the boottime has not. + do { + gettimeofday(&now, NULL); + after_now = KernelBootTimeInNanoseconds(); + } while (after_now != before_now); + return (int64_t)now.tv_sec * NSEC_PER_MSEC + (int64_t)now.tv_usec - before_now; +} + +// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE. +@implementation GDTCORClock + +- (instancetype)init { + self = [super init]; + if (self) { + _kernelBootTime = KernelBootTimeInNanoseconds(); + _uptime = UptimeInNanoseconds(); + _timeMillis = + (int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC); + CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem(); + _timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0); + CFRelease(timeZoneRef); + } + return self; +} + ++ (GDTCORClock *)snapshot { + return [[GDTCORClock alloc] init]; +} + ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture { + GDTCORClock *snapshot = [self snapshot]; + snapshot->_timeMillis += millisInTheFuture; + return snapshot; +} + +- (BOOL)isAfter:(GDTCORClock *)otherClock { + // These clocks are trivially comparable when they share a kernel boot time. + if (_kernelBootTime == otherClock->_kernelBootTime) { + int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) - + (otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds); + return timeDiff > 0; + } else { + int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime; + // This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO + // is returned. This can be altered by changing the system time and rebooting. + return kernelBootTimeDiff < 0 ? YES : NO; + } +} + +- (NSUInteger)hash { + return [@(_kernelBootTime) hash] ^ [@(_uptime) hash] ^ [@(_timeMillis) hash] ^ + [@(_timezoneOffsetSeconds) hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - NSSecureCoding + +/** NSKeyedCoder key for timeMillis property. */ +static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis"; + +/** NSKeyedCoder key for timezoneOffsetMillis property. */ +static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds"; + +/** NSKeyedCoder key for _kernelBootTime ivar. */ +static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime"; + +/** NSKeyedCoder key for _uptime ivar. */ +static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + // TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and + // uptimeMillis ivars + _timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey]; + _timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds]; + _kernelBootTime = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime]; + _uptime = [aDecoder decodeInt64ForKey:kGDTCORClockUptime]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey]; + [aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds]; + [aCoder encodeInt64:_kernelBootTime forKey:kGDTCORClockKernelBootTime]; + [aCoder encodeInt64:_uptime forKey:kGDTCORClockUptime]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m new file mode 100644 index 00000000..0f5170d0 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m @@ -0,0 +1,55 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h" + +volatile NSInteger GDTCORConsoleLoggerLoggingLevel = GDTCORLoggingLevelErrors; + +/** The console logger prefix. */ +static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]"; + +NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) { + return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code]; +} + +void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + if (logLevel >= GDTCORConsoleLoggerLoggingLevel) { + NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); + } +#endif // !NDEBUG +} + +void GDTCORLogAssert( + BOOL wasFatal, NSString *_Nonnull file, NSInteger line, NSString *_Nullable format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + GDTCORMessageCode code = wasFatal ? GDTCORMCEFatalAssertion : GDTCORMCEGeneralError; + NSString *logFormat = + [NSString stringWithFormat:@"%@[%@] (%@:%ld) : %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), file, (long)line, format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); +#endif // !NDEBUG +} diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m new file mode 100644 index 00000000..04903d47 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m @@ -0,0 +1,59 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORDataFuture.h" + +@implementation GDTCORDataFuture + +- (instancetype)initWithFileURL:(NSURL *)fileURL { + self = [super init]; + if (self) { + _fileURL = fileURL; + } + return self; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (NSUInteger)hash { + // In reality, only one of these should be populated. + return [_fileURL hash]; +} + +#pragma mark - NSSecureCoding + +/** Coding key for _fileURL ivar. */ +static NSString *kGDTCORDataFutureFileURLKey = @"GDTCORDataFutureFileURLKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_fileURL forKey:kGDTCORDataFutureFileURLKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [self init]; + if (self) { + _fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTCORDataFutureFileURLKey]; + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m new file mode 100644 index 00000000..5c79a4bc --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m @@ -0,0 +1,258 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCOREvent.h" + +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORDataFuture.h" +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" + +@implementation GDTCOREvent + ++ (NSNumber *)nextEventID { + static unsigned long long nextEventID = 0; + static NSString *counterPath; + static dispatch_queue_t eventIDQueue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventIDQueue = dispatch_queue_create("com.google.GDTCOREventIDQueue", DISPATCH_QUEUE_SERIAL); + counterPath = GDTCORRootDirectory().path; + counterPath = [NSString stringWithFormat:@"%@/count", counterPath]; + NSError *error; + NSString *countText = [NSString stringWithContentsOfFile:counterPath + encoding:NSUTF8StringEncoding + error:&error]; + const char *countChars = [countText UTF8String]; + unsigned long long count = 0ULL; + if (countChars) { + count = strtoull([countText UTF8String], NULL, 10); + } + nextEventID = error ? 0 : count; + }); + + __block NSNumber *result; + dispatch_sync(eventIDQueue, ^{ + result = @(nextEventID); + nextEventID++; + NSError *error; + [[result stringValue] writeToFile:counterPath + atomically:YES + encoding:NSUTF8StringEncoding + error:&error]; + GDTCORAssert(error == nil, @"There was an error saving the new counter value to disk: %@", + error); + }); + return result; +} + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _eventID = [GDTCOREvent nextEventID]; + _mappingID = mappingID; + _target = target; + _qosTier = GDTCOREventQosDefault; + } + GDTCORLogDebug(@"Event %@ created. mappingID: %@ target:%ld", self, mappingID, (long)target); + return self; +} + +- (instancetype)copy { + GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; + copy->_eventID = _eventID; + copy.dataObject = _dataObject; + copy.qosTier = _qosTier; + copy.clockSnapshot = _clockSnapshot; + copy.customBytes = _customBytes; + copy->_GDTFilePath = _GDTFilePath; + GDTCORLogDebug(@"Copying event %@ to event %@", self, copy); + return copy; +} + +- (NSUInteger)hash { + // This loses some precision, but it's probably fine. + NSUInteger eventIDHash = [_eventID hash]; + NSUInteger mappingIDHash = [_mappingID hash]; + NSUInteger timeHash = [_clockSnapshot hash]; + NSInteger dataObjectHash = [_dataObject hash]; + NSUInteger fileURL = [_GDTFilePath hash]; + + return eventIDHash ^ mappingIDHash ^ _target ^ _qosTier ^ timeHash ^ dataObjectHash ^ fileURL; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - Property overrides + +- (void)setDataObject:(id)dataObject { + // If you're looking here because of a performance issue in -transportBytes slowing the assignment + // of -dataObject, one way to address this is to add a queue to this class, + // dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync. + if (dataObject != _dataObject) { + _dataObject = dataObject; + } +} + +- (NSURL *)fileURL { + if (!_GDTFilePath) { + _GDTFilePath = [NSString stringWithFormat:@"event-%lu", (unsigned long)self.hash]; + } + return [GDTCORRootDirectory() URLByAppendingPathComponent:_GDTFilePath]; +} + +#pragma mark - Private methods + +- (BOOL)writeToGDTPath:(NSString *)filePath error:(NSError **)error { + NSData *dataTransportBytes = [_dataObject transportBytes]; + if (dataTransportBytes == nil) { + _GDTFilePath = nil; + _dataObject = nil; + return NO; + } + NSURL *fileURL = [GDTCORRootDirectory() URLByAppendingPathComponent:filePath]; + BOOL writingSuccess = [dataTransportBytes writeToURL:fileURL + options:NSDataWritingAtomic + error:error]; + if (!writingSuccess) { + GDTCORLogError(GDTCORMCEFileWriteError, @"An event file could not be written: %@", fileURL); + return NO; + } + _GDTFilePath = filePath; + _dataObject = nil; + return YES; +} + +#pragma mark - NSSecureCoding and NSCoding Protocols + +/** NSCoding key for eventID property. */ +static NSString *eventIDKey = @"_eventID"; + +/** NSCoding key for mappingID property. */ +static NSString *mappingIDKey = @"_mappingID"; + +/** NSCoding key for target property. */ +static NSString *targetKey = @"_target"; + +/** NSCoding key for qosTier property. */ +static NSString *qosTierKey = @"_qosTier"; + +/** NSCoding key for clockSnapshot property. */ +static NSString *clockSnapshotKey = @"_clockSnapshot"; + +/** NSCoding key for fileURL property. */ +static NSString *fileURLKey = @"_fileURL"; + +/** NSCoding key for GDTFilePath property. */ +static NSString *kGDTFilePathKey = @"_GDTFilePath"; + +/** NSCoding key for backwards compatibility of GDTCORStoredEvent mappingID property.*/ +static NSString *kStoredEventMappingIDKey = @"GDTCORStoredEventMappingIDKey"; + +/** NSCoding key for backwards compatibility of GDTCORStoredEvent target property.*/ +static NSString *kStoredEventTargetKey = @"GDTCORStoredEventTargetKey"; + +/** NSCoding key for backwards compatibility of GDTCORStoredEvent qosTier property.*/ +static NSString *kStoredEventQosTierKey = @"GDTCORStoredEventQosTierKey"; + +/** NSCoding key for backwards compatibility of GDTCORStoredEvent clockSnapshot property.*/ +static NSString *kStoredEventClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey"; + +/** NSCoding key for backwards compatibility of GDTCORStoredEvent dataFuture property.*/ +static NSString *kStoredEventDataFutureKey = @"GDTCORStoredEventDataFutureKey"; + +/** NSCoding key for customData property. */ +static NSString *kCustomDataKey = @"GDTCOREventCustomDataKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + GDTCORDataFuture *dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture class] + forKey:kStoredEventDataFutureKey]; + if (dataFuture) { + return [self initWithCoderForStoredEventBackwardCompatibility:aDecoder + fileURL:dataFuture.fileURL]; + } + NSString *mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:mappingIDKey]; + NSInteger target = [aDecoder decodeIntegerForKey:targetKey]; + self = [self initWithMappingID:mappingID target:target]; + if (self) { + _eventID = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:eventIDKey]; + if (_eventID == nil) { + _eventID = [GDTCOREvent nextEventID]; + } + _qosTier = [aDecoder decodeIntegerForKey:qosTierKey]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey]; + NSURL *fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:fileURLKey]; + if (fileURL) { + _GDTFilePath = [fileURL lastPathComponent]; + } else { + _GDTFilePath = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGDTFilePathKey]; + } + _customBytes = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCustomDataKey]; + } + return self; +} + +- (id)initWithCoderForStoredEventBackwardCompatibility:(NSCoder *)aDecoder + fileURL:(NSURL *)fileURL { + NSString *mappingID = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kStoredEventMappingIDKey]; + NSInteger target = [[aDecoder decodeObjectOfClass:[NSNumber class] + forKey:kStoredEventTargetKey] integerValue]; + self = [self initWithMappingID:mappingID target:target]; + if (self) { + _eventID = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:eventIDKey]; + if (_eventID == nil) { + _eventID = [GDTCOREvent nextEventID]; + } + _qosTier = [[aDecoder decodeObjectOfClass:[NSNumber class] + forKey:kStoredEventQosTierKey] integerValue]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] + forKey:kStoredEventClockSnapshotKey]; + if (fileURL) { + _GDTFilePath = [fileURL lastPathComponent]; + } else { + _GDTFilePath = [aDecoder decodeObjectOfClass:[NSString class] forKey:kGDTFilePathKey]; + } + _customBytes = [aDecoder decodeObjectOfClass:[NSData class] forKey:kCustomDataKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_eventID forKey:eventIDKey]; + [aCoder encodeObject:_mappingID forKey:mappingIDKey]; + [aCoder encodeInteger:_target forKey:targetKey]; + [aCoder encodeInteger:_qosTier forKey:qosTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:clockSnapshotKey]; + [aCoder encodeObject:_GDTFilePath forKey:kGDTFilePathKey]; + [aCoder encodeObject:_customBytes forKey:kCustomDataKey]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m new file mode 100644 index 00000000..d50cf0aa --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m @@ -0,0 +1,411 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORFlatFileStorage.h" + +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +@implementation GDTCORFlatFileStorage + ++ (void)load { + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerStorage:[self sharedInstance] target:kGDTCORTargetCSH]; + + // Sets a global translation mapping to decode GDTCORStoredEvent objects encoded as instances of + // GDTCOREvent instead. Then we do the same thing with GDTCORStorage. This must be done in load + // because there are no direct references to this class and the NSCoding methods won't be called + // unless the class name is mapped early. + [NSKeyedUnarchiver setClass:[GDTCOREvent class] forClassName:@"GDTCORStoredEvent"]; + [NSKeyedUnarchiver setClass:[GDTCORFlatFileStorage class] forClassName:@"GDTCORStorage"]; +} + ++ (NSString *)archivePath { + static NSString *archivePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + archivePath = + [GDTCORRootDirectory() URLByAppendingPathComponent:@"GDTCORFlatFileStorageArchive"].path; + }); + return archivePath; +} + ++ (NSString *)libraryDataPath { + static NSString *libraryDataPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + libraryDataPath = + [GDTCORRootDirectory() URLByAppendingPathComponent:NSStringFromClass([self class]) + isDirectory:YES] + .path; + libraryDataPath = [libraryDataPath stringByAppendingPathComponent:@"gdt_library_data"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:libraryDataPath isDirectory:NULL]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:libraryDataPath + withIntermediateDirectories:YES + attributes:0 + error:&error]; + GDTCORAssert(error == nil, @"Creating the library data path failed: %@", error); + } + }); + return libraryDataPath; +} + ++ (instancetype)sharedInstance { + static GDTCORFlatFileStorage *sharedStorage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedStorage = [[GDTCORFlatFileStorage alloc] init]; + }); + return sharedStorage; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _storageQueue = + dispatch_queue_create("com.google.GDTCORFlatFileStorage", DISPATCH_QUEUE_SERIAL); + _targetToEventSet = [[NSMutableDictionary alloc] init]; + _storedEvents = [[NSMutableDictionary alloc] init]; + _uploadCoordinator = [GDTCORUploadCoordinator sharedInstance]; + } + return self; +} + +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORLogDebug(@"Saving event: %@", event); + if (event == nil) { + GDTCORLogDebug(@"%@", @"The event was nil, so it was not saved."); + return; + } + BOOL hadOriginalCompletion = completion != nil; + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + GDTCORLogDebug(@"event %@ stored. success:%@ error:%@", event, wasWritten ? @"YES" : @"NO", + error); + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + // End the background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + dispatch_async(_storageQueue, ^{ + // Check that a backend implementation is available for this target. + NSInteger target = event.target; + + // Check that a prioritizer is available for this target. + id prioritizer = + [GDTCORRegistrar sharedInstance].targetToPrioritizer[@(target)]; + GDTCORAssert(prioritizer, @"There's no prioritizer registered for the given target. Are you " + @"sure you've added the support library for the backend you need?"); + + // Write the transport bytes to disk, get a filename. + GDTCORAssert([event.dataObject transportBytes], + @"The event should have been serialized to bytes"); + NSError *error = nil; + NSURL *eventFile = [self saveEventBytesToDisk:event eventHash:event.hash error:&error]; + if (!eventFile || error) { + GDTCORLogError(GDTCORMCEFileWriteError, @"Event failed to save to disk: %@", error); + completion(NO, error); + return; + } else { + GDTCORLogDebug(@"Event saved to disk: %@", eventFile); + completion(YES, error); + } + + // Add event to tracking collections. + [self addEventToTrackingCollections:event]; + + // Have the prioritizer prioritize the event and save state if there was an onComplete block. + [prioritizer prioritizeEvent:event]; + if (hadOriginalCompletion && [prioritizer respondsToSelector:@selector(saveState)]) { + [prioritizer saveState]; + GDTCORLogDebug(@"Prioritizer %@ has saved state due to an event's onComplete block.", + prioritizer); + } + + // Check the QoS, if it's high priority, notify the target that it has a high priority event. + if (event.qosTier == GDTCOREventQoSFast) { + [self.uploadCoordinator forceUploadForTarget:target]; + } + + // Write state to disk if there was an onComplete block or if we're in the background. + if (hadOriginalCompletion || [[GDTCORApplication sharedApplication] isRunningInBackground]) { + if (hadOriginalCompletion) { + GDTCORLogDebug(@"%@", + @"Saving flat file storage state because a completion block was passed."); + } else { + GDTCORLogDebug( + @"%@", @"Saving flat file storage state because the app is running in the background"); + } + NSError *error; + GDTCOREncodeArchive(self, [GDTCORFlatFileStorage archivePath], &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCORFlatFileStorage to an archive failed: %@", error); + } + } + + // Cancel or end the associated background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + GDTCORLogDebug(@"Event %@ is stored. There are %ld events stored on disk", event, + (unsigned long)self->_storedEvents.count); + }); +} + +- (void)removeEvents:(NSSet *)eventIDs { + NSSet *eventsToRemove = [eventIDs copy]; + dispatch_async(_storageQueue, ^{ + for (NSNumber *eventID in eventsToRemove) { + // Remove from disk, first and foremost. + GDTCOREvent *event = self->_storedEvents[eventID]; + if (event) { + NSError *error; + if (event.fileURL) { + NSURL *fileURL = event.fileURL; + BOOL result = [[NSFileManager defaultManager] removeItemAtPath:fileURL.path error:&error]; + if (!result || error) { + GDTCORLogWarning(GDTCORMCWFileReadError, + @"There was an error removing an event file: %@", error); + } else { + GDTCORLogDebug(@"Removed event from disk: %@", fileURL); + } + } + + // Remove from the tracking collections. + [self.storedEvents removeObjectForKey:event.eventID]; + [self.targetToEventSet[@(event.target)] removeObject:event]; + } + } + }); +} + +#pragma mark - GDTCORStorageProtocol + +- (void)libraryDataForKey:(nonnull NSString *)key + onComplete: + (nonnull void (^)(NSData *_Nullable, NSError *_Nullable error))onComplete { + dispatch_async(_storageQueue, ^{ + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + NSError *error; + NSData *data = [NSData dataWithContentsOfFile:dataPath options:0 error:&error]; + if (onComplete) { + onComplete(data, error); + } + }); +} + +- (void)storeLibraryData:(NSData *)data + forKey:(nonnull NSString *)key + onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete { + if (!data || data.length <= 0) { + if (onComplete) { + onComplete([NSError errorWithDomain:NSInternalInconsistencyException code:-1 userInfo:nil]); + } + return; + } + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + [data writeToFile:dataPath options:NSDataWritingAtomic error:&error]; + if (onComplete) { + onComplete(error); + } + }); +} + +- (void)removeLibraryDataForKey:(nonnull NSString *)key + onComplete:(nonnull void (^)(NSError *_Nullable error))onComplete { + dispatch_async(_storageQueue, ^{ + NSError *error; + NSString *dataPath = [[[self class] libraryDataPath] stringByAppendingPathComponent:key]; + if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath]) { + [[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error]; + if (onComplete) { + onComplete(error); + } + } + }); +} + +#pragma mark - Private helper methods + +/** Saves the event's dataObject to a file using NSData mechanisms. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param event The event. + * @param eventHash The hash value of the event. + * @return The filename + */ +- (NSURL *)saveEventBytesToDisk:(GDTCOREvent *)event + eventHash:(NSUInteger)eventHash + error:(NSError **)error { + NSString *eventFileName = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash]; + NSError *writingError; + [event writeToGDTPath:eventFileName error:&writingError]; + if (writingError) { + GDTCORLogDebug(@"There was an error saving an event to disk: %@", writingError); + } + return event.fileURL; +} + +/** Adds the event to internal tracking collections. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param event The event to track. + */ +- (void)addEventToTrackingCollections:(GDTCOREvent *)event { + _storedEvents[event.eventID] = event; + NSNumber *target = @(event.target); + NSMutableSet *events = self.targetToEventSet[target]; + events = events ? events : [[NSMutableSet alloc] init]; + [events addObject:event]; + _targetToEventSet[target] = events; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + dispatch_async(_storageQueue, ^{ + NSError *error; + GDTCORDecodeArchive([GDTCORFlatFileStorage class], [GDTCORFlatFileStorage archivePath], nil, + &error); + if (error) { + GDTCORLogDebug(@"Deserializing GDTCORFlatFileStorage from an archive failed: %@", error); + } + }); +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_storageQueue, ^{ + // Immediately request a background task to run until the end of the current queue of work, and + // cancel it once the work is done. + __block GDTCORBackgroundIdentifier bgID = + [app beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + NSError *error; + GDTCOREncodeArchive(self, [GDTCORFlatFileStorage archivePath], &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCORFlatFileStorage to an archive failed: %@", error); + } else { + GDTCORLogDebug(@"Serialized GDTCORFlatFileStorage to %@", + [GDTCORFlatFileStorage archivePath]); + } + + // End the background task if it's still valid. + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_storageQueue, ^{ + NSError *error; + GDTCOREncodeArchive(self, [GDTCORFlatFileStorage archivePath], &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCORFlatFileStorage to an archive failed: %@", error); + } else { + GDTCORLogDebug(@"Serialized GDTCORFlatFileStorage to %@", + [GDTCORFlatFileStorage archivePath]); + } + }); +} + +#pragma mark - NSSecureCoding + +/** The NSKeyedCoder key for the storedEvents property. */ +static NSString *const kGDTCORFlatFileStorageStoredEventsKey = @"GDTCORStorageStoredEventsKey"; + +/** The NSKeyedCoder key for the targetToEventSet property. */ +static NSString *const kGDTCORFlatFileStorageTargetToEventSetKey = + @"GDTCORStorageTargetToEventSetKey"; + +/** The NSKeyedCoder key for the uploadCoordinator property. */ +static NSString *const kGDTCORFlatFileStorageUploadCoordinatorKey = + @"GDTCORStorageUploadCoordinatorKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + // Create the singleton and populate its ivars. + GDTCORFlatFileStorage *sharedInstance = [self.class sharedInstance]; + NSSet *classes = [NSSet setWithObjects:[NSMutableOrderedSet class], [NSMutableDictionary class], + [GDTCOREvent class], nil]; + id storedEvents = [aDecoder decodeObjectOfClasses:classes + forKey:kGDTCORFlatFileStorageStoredEventsKey]; + NSMutableDictionary *events = [[NSMutableDictionary alloc] init]; + if ([storedEvents isKindOfClass:[NSMutableOrderedSet class]]) { + [(NSMutableOrderedSet *)storedEvents + enumerateObjectsUsingBlock:^(GDTCOREvent *_Nonnull obj, NSUInteger idx, + BOOL *_Nonnull stop) { + events[obj.eventID] = obj; + }]; + } else if ([storedEvents isKindOfClass:[NSMutableDictionary class]]) { + events = (NSMutableDictionary *)storedEvents; + } + sharedInstance->_storedEvents = events; + classes = [NSSet + setWithObjects:[NSMutableDictionary class], [NSMutableSet class], [GDTCOREvent class], nil]; + sharedInstance->_targetToEventSet = + [aDecoder decodeObjectOfClasses:classes forKey:kGDTCORFlatFileStorageTargetToEventSetKey]; + sharedInstance->_uploadCoordinator = + [aDecoder decodeObjectOfClass:[GDTCORUploadCoordinator class] + forKey:kGDTCORFlatFileStorageUploadCoordinatorKey]; + return sharedInstance; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + GDTCORFlatFileStorage *sharedInstance = [self.class sharedInstance]; + NSMutableDictionary *storedEvents = sharedInstance->_storedEvents; + if (storedEvents) { + [aCoder encodeObject:storedEvents forKey:kGDTCORFlatFileStorageStoredEventsKey]; + } + NSMutableDictionary *> *targetToEventSet = + sharedInstance->_targetToEventSet; + if (targetToEventSet) { + [aCoder encodeObject:targetToEventSet forKey:kGDTCORFlatFileStorageTargetToEventSetKey]; + } + GDTCORUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator; + if (uploadCoordinator) { + [aCoder encodeObject:uploadCoordinator forKey:kGDTCORFlatFileStorageUploadCoordinatorKey]; + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m new file mode 100644 index 00000000..9228c346 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m @@ -0,0 +1,119 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORLifecycle.h" + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +@implementation GDTCORLifecycle + ++ (void)load { + [self sharedInstance]; +} + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance { + static GDTCORLifecycle *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORLifecycle alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:kGDTCORApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(applicationWillEnterForeground:) + name:kGDTCORApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = kGDTCORApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(applicationWillTerminate:) + name:name + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)applicationDidEnterBackground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is backgrounding."); + [[GDTCORTransformer sharedInstance] appWillBackground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is backgrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillBackground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is backgrounding."); + [[GDTCORRegistrar sharedInstance] appWillBackground:application]; + } +} + +- (void)applicationWillEnterForeground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is foregrounding."); + [[GDTCORTransformer sharedInstance] appWillForeground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is foregrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillForeground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is foregrounding."); + [[GDTCORRegistrar sharedInstance] appWillForeground:application]; + } +} + +- (void)applicationWillTerminate:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORTransformer that the app is terminating."); + [[GDTCORTransformer sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORUploadCoordinator that the app is terminating."); + [[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug(@"%@", @"Signaling GDTCORRegistrar that the app is terminating."); + [[GDTCORRegistrar sharedInstance] appWillTerminate:application]; + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m new file mode 100644 index 00000000..d0fea431 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m @@ -0,0 +1,555 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORPlatform.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#ifdef GDTCOR_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION); +#else +NSString *const kGDTCORVersion = @"Unknown"; +#endif // GDTCOR_VERSION + +const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0; + +NSString *const kGDTCORApplicationDidEnterBackgroundNotification = + @"GDTCORApplicationDidEnterBackgroundNotification"; + +NSString *const kGDTCORApplicationWillEnterForegroundNotification = + @"GDTCORApplicationWillEnterForegroundNotification"; + +NSString *const kGDTCORApplicationWillTerminateNotification = + @"GDTCORApplicationWillTerminateNotification"; + +NSURL *GDTCORRootDirectory(void) { + static NSURL *GDTPath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cachePath = + NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; + GDTPath = + [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/google-sdks-events", cachePath]]; + GDTCORLogDebug(@"GDT's state will be saved to: %@", GDTPath); + if (![[NSFileManager defaultManager] fileExistsAtPath:GDTPath.path]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:GDTPath.path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + GDTCORAssert(error == nil, @"There was an error creating GDT's path"); + } + }); + return GDTPath; +} + +BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags) { +#if !TARGET_OS_WATCH + BOOL reachable = + (flags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable; + BOOL connectionRequired = (flags & kSCNetworkReachabilityFlagsConnectionRequired) == + kSCNetworkReachabilityFlagsConnectionRequired; + return reachable && !connectionRequired; +#else + return (flags & kGDTCORNetworkReachabilityFlagsReachable) == + kGDTCORNetworkReachabilityFlagsReachable; +#endif +} + +BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags) { +#if TARGET_OS_IOS + return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN; +#else + // Assume network connection not WWAN on macOS, tvOS, watchOS. + return NO; +#endif // TARGET_OS_IOS +} + +GDTCORNetworkType GDTCORNetworkTypeMessage() { +#if !TARGET_OS_WATCH + SCNetworkReachabilityFlags reachabilityFlags = [GDTCORReachability currentFlags]; + if ((reachabilityFlags & kSCNetworkReachabilityFlagsReachable) == + kSCNetworkReachabilityFlagsReachable) { + if (GDTCORReachabilityFlagsContainWWAN(reachabilityFlags)) { + return GDTCORNetworkTypeMobile; + } else { + return GDTCORNetworkTypeWIFI; + } + } +#endif + return GDTCORNetworkTypeUNKNOWN; +} + +GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage() { +#if TARGET_OS_IOS + static NSDictionary *CTRadioAccessTechnologyToNetworkSubTypeMessage; + static CTTelephonyNetworkInfo *networkInfo; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + CTRadioAccessTechnologyToNetworkSubTypeMessage = @{ + CTRadioAccessTechnologyGPRS : @(GDTCORNetworkMobileSubtypeGPRS), + CTRadioAccessTechnologyEdge : @(GDTCORNetworkMobileSubtypeEdge), + CTRadioAccessTechnologyWCDMA : @(GDTCORNetworkMobileSubtypeWCDMA), + CTRadioAccessTechnologyHSDPA : @(GDTCORNetworkMobileSubtypeHSDPA), + CTRadioAccessTechnologyHSUPA : @(GDTCORNetworkMobileSubtypeHSUPA), + CTRadioAccessTechnologyCDMA1x : @(GDTCORNetworkMobileSubtypeCDMA1x), + CTRadioAccessTechnologyCDMAEVDORev0 : @(GDTCORNetworkMobileSubtypeCDMAEVDORev0), + CTRadioAccessTechnologyCDMAEVDORevA : @(GDTCORNetworkMobileSubtypeCDMAEVDORevA), + CTRadioAccessTechnologyCDMAEVDORevB : @(GDTCORNetworkMobileSubtypeCDMAEVDORevB), + CTRadioAccessTechnologyeHRPD : @(GDTCORNetworkMobileSubtypeHRPD), + CTRadioAccessTechnologyLTE : @(GDTCORNetworkMobileSubtypeLTE), + }; + networkInfo = [[CTTelephonyNetworkInfo alloc] init]; + }); + NSString *networkCurrentRadioAccessTechnology; +#if TARGET_OS_MACCATALYST + NSDictionary *networkCurrentRadioAccessTechnologyDict = + networkInfo.serviceCurrentRadioAccessTechnology; + if (networkCurrentRadioAccessTechnologyDict.count) { + networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0]; + } +#else // TARGET_OS_MACCATALYST +#if defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + if (@available(iOS 12.0, *)) { + NSDictionary *networkCurrentRadioAccessTechnologyDict = + networkInfo.serviceCurrentRadioAccessTechnology; + if (networkCurrentRadioAccessTechnologyDict.count) { + // In iOS 12, multiple radio technologies can be captured. We prefer not particular radio + // tech to another, so we'll just return the first value in the dictionary. + networkCurrentRadioAccessTechnology = networkCurrentRadioAccessTechnologyDict.allValues[0]; + } + } else { +#else // defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + networkCurrentRadioAccessTechnology = networkInfo.currentRadioAccessTechnology; +#endif // // defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 + } +#endif // TARGET_OS_MACCATALYST + if (networkCurrentRadioAccessTechnology) { + NSNumber *networkMobileSubtype = + CTRadioAccessTechnologyToNetworkSubTypeMessage[networkCurrentRadioAccessTechnology]; + return networkMobileSubtype.intValue; + } else { + return GDTCORNetworkMobileSubtypeUNKNOWN; + } +#else + return GDTCORNetworkMobileSubtypeUNKNOWN; +#endif +} + +NSData *_Nullable GDTCOREncodeArchive(id obj, + NSString *archivePath, + NSError *_Nullable *error) { + NSData *resultData; +#if (defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__MAC_10_13) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300) || \ + (defined(__TVOS_11_0) && __TV_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__WATCHOS_4_0) && __WATCH_OS_VERSION_MAX_ALLOWED >= 040000) || \ + (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4, *)) { + resultData = [NSKeyedArchiver archivedDataWithRootObject:obj + requiringSecureCoding:YES + error:error]; + if (*error) { + GDTCORLogDebug(@"Encoding an object failed: %@", *error); + return nil; + } + if (archivePath) { + BOOL result = [resultData writeToFile:archivePath options:NSDataWritingAtomic error:error]; + if (result == NO || *error) { + GDTCORLogDebug(@"Attempt to write archive failed: URL:%@ error:%@", archivePath, *error); + } else { + GDTCORLogDebug(@"Writing archive succeeded: %@", archivePath); + } + } + } else { +#endif + BOOL result = NO; + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + resultData = [NSKeyedArchiver archivedDataWithRootObject:obj]; +#pragma clang diagnostic pop + if (archivePath) { + result = [resultData writeToFile:archivePath options:NSDataWritingAtomic error:error]; + if (result == NO || *error) { + GDTCORLogDebug(@"Attempt to write archive failed: URL:%@ error:%@", archivePath, *error); + } else { + GDTCORLogDebug(@"Writing archive succeeded: %@", archivePath); + } + } + } @catch (NSException *exception) { + NSString *errorString = + [NSString stringWithFormat:@"An exception was thrown during encoding: %@", exception]; + *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : errorString}]; + } + GDTCORLogDebug(@"Attempt to write archive. successful:%@ URL:%@ error:%@", + result ? @"YES" : @"NO", archivePath, *error); + } + return resultData; +} + +id _Nullable GDTCORDecodeArchive(Class archiveClass, + NSString *_Nullable archivePath, + NSData *_Nullable archiveData, + NSError *_Nullable *error) { + id unarchivedObject = nil; +#if (defined(__IPHONE_11_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__MAC_10_13) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101300) || \ + (defined(__TVOS_11_0) && __TV_OS_VERSION_MAX_ALLOWED >= 110000) || \ + (defined(__WATCHOS_4_0) && __WATCH_OS_VERSION_MAX_ALLOWED >= 040000) || \ + (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4, *)) { + NSData *data = archiveData ? archiveData : [NSData dataWithContentsOfFile:archivePath]; + if (data) { + unarchivedObject = [NSKeyedUnarchiver unarchivedObjectOfClass:archiveClass + fromData:data + error:error]; + } + } else { +#endif + @try { + NSData *archivedData = + archiveData ? archiveData : [NSData dataWithContentsOfFile:archivePath]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + NSString *errorString = + [NSString stringWithFormat:@"An exception was thrown during encoding: %@", exception]; + *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : errorString}]; + } + } + return unarchivedObject; +} + +@interface GDTCORApplication () +/** + Private flag to match the existing `readonly` public flag. This will be accurate for all platforms, + since we handle each platform's lifecycle notifications separately. + */ +@property(atomic, readwrite) BOOL isRunningInBackground; + +@end + +@implementation GDTCORApplication + +#if TARGET_OS_WATCH +/** A dispatch queue on which all task semaphores will populate and remove from + * gBackgroundIdentifierToSemaphoreMap. + */ +static dispatch_queue_t gSemaphoreQueue; + +/** For mapping backgroundIdentifier to task semaphore. */ +static NSMutableDictionary *gBackgroundIdentifierToSemaphoreMap; +#endif + ++ (void)load { + GDTCORLogDebug( + @"%@", @"GDT is initializing. Please note that if you quit the app via the " + "debugger and not through a lifecycle event, event data will remain on disk but " + "storage won't have a reference to them since the singleton wasn't saved to disk."); +#if TARGET_OS_IOS || TARGET_OS_TV + // If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues. + GDTCORFatalAssert( + GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid, + @"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same."); +#endif + [self sharedApplication]; +} + ++ (void)initialize { +#if TARGET_OS_WATCH + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSemaphoreQueue = dispatch_queue_create("com.google.GDTCORApplication", DISPATCH_QUEUE_SERIAL); + GDTCORLogDebug( + @"%@", + @"GDTCORApplication is initializing on watchOS, gSemaphoreQueue has been initialized."); + gBackgroundIdentifierToSemaphoreMap = [[NSMutableDictionary alloc] init]; + GDTCORLogDebug(@"%@", @"GDTCORApplication is initializing on watchOS, " + @"gBackgroundIdentifierToSemaphoreMap has been initialized."); + }); +#endif +} + ++ (nullable GDTCORApplication *)sharedApplication { + static GDTCORApplication *application; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + application = [[GDTCORApplication alloc] init]; + }); + return application; +} + +- (instancetype)init { + self = [super init]; + if (self) { + // This class will be instantiated in the foreground. + _isRunningInBackground = NO; + +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = UIApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillTerminate:) + name:name + object:nil]; + +#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13, tvOS 13.0, *)) { + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UISceneWillEnterForegroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UISceneWillDeactivateNotification + object:nil]; + } +#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + +#elif TARGET_OS_OSX + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(macOSApplicationWillTerminate:) + name:NSApplicationWillTerminateNotification + object:nil]; + +#elif TARGET_OS_WATCH + // TODO: Notification on watchOS platform is currently posted by strings which are frangible. + // TODO: Needs improvements here. + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:@"UIApplicationDidEnterBackgroundNotification" + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:@"UIApplicationWillEnterForegroundNotification" + object:nil]; + + // Adds observers for app extension on watchOS platform + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:NSExtensionHostDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:NSExtensionHostWillEnterForegroundNotification + object:nil]; +#endif + } + return self; +} + +#if TARGET_OS_WATCH +/** Generates and maps a unique background identifier to the given semaphore. + * + * @param semaphore The semaphore to map. + * @return A unique GDTCORBackgroundIdentifier mapped to the given semaphore. + */ ++ (GDTCORBackgroundIdentifier)createAndMapBackgroundIdentifierToSemaphore: + (dispatch_semaphore_t)semaphore { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + dispatch_queue_t queue = gSemaphoreQueue; + NSMutableDictionary *map = gBackgroundIdentifierToSemaphoreMap; + if (queue && map) { + dispatch_sync(queue, ^{ + bgID = arc4random(); + NSNumber *bgIDNumber = @(bgID); + while (bgID == GDTCORBackgroundIdentifierInvalid || map[bgIDNumber]) { + bgID = arc4random(); + bgIDNumber = @(bgID); + } + map[bgIDNumber] = semaphore; + }); + } + return bgID; +} + +/** Returns the semaphore mapped to given bgID and removes the value from the map. + * + * @param bgID The unique NSUInteger as GDTCORBackgroundIdentifier. + * @return The semaphore mapped by given bgID. + */ ++ (dispatch_semaphore_t)semaphoreForBackgroundIdentifier:(GDTCORBackgroundIdentifier)bgID { + __block dispatch_semaphore_t semaphore; + dispatch_queue_t queue = gSemaphoreQueue; + NSMutableDictionary *map = gBackgroundIdentifierToSemaphoreMap; + NSNumber *bgIDNumber = @(bgID); + if (queue && map) { + dispatch_sync(queue, ^{ + semaphore = map[bgIDNumber]; + [map removeObjectForKey:bgIDNumber]; + }); + } + return semaphore; +} +#endif + +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^)(void))handler { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; +#if !TARGET_OS_WATCH + bgID = [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name + expirationHandler:handler]; +#if !NDEBUG + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Creating background task with name:%@ bgID:%ld", name, (long)bgID); + } +#endif // !NDEBUG +#elif TARGET_OS_WATCH + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + bgID = [GDTCORApplication createAndMapBackgroundIdentifierToSemaphore:semaphore]; + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Creating activity with name:%@ bgID:%ld on watchOS.", name, (long)bgID); + } + [[self sharedNSProcessInfoForBackgroundTask] + performExpiringActivityWithReason:name + usingBlock:^(BOOL expired) { + if (expired) { + if (handler) { + handler(); + } + dispatch_semaphore_signal(semaphore); + GDTCORLogDebug( + @"Activity with name:%@ bgID:%ld on watchOS is expiring.", + name, (long)bgID); + } else { + dispatch_semaphore_wait( + semaphore, + dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC)); + } + }]; +#endif + return bgID; +} + +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID { +#if !TARGET_OS_WATCH + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug(@"Ending background task with ID:%ld was successful", (long)bgID); + [[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID]; + return; + } +#elif TARGET_OS_WATCH + if (bgID != GDTCORBackgroundIdentifierInvalid) { + dispatch_semaphore_t semaphore = [GDTCORApplication semaphoreForBackgroundIdentifier:bgID]; + GDTCORLogDebug(@"Ending activity with bgID:%ld on watchOS.", (long)bgID); + if (semaphore) { + dispatch_semaphore_signal(semaphore); + GDTCORLogDebug(@"Signaling semaphore with bgID:%ld on watchOS.", (long)bgID); + } else { + GDTCORLogDebug(@"Semaphore with bgID:%ld is nil on watchOS.", (long)bgID); + } + } +#endif // !TARGET_OS_WATCH +} + +#pragma mark - App environment helpers + +- (BOOL)isAppExtension { + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +} + +/** Returns a UIApplication or NSProcessInfo instance if on the appropriate platform. + * + * @return The shared UIApplication or NSProcessInfo if on the appropriate platform. + */ +#if TARGET_OS_IOS || TARGET_OS_TV +- (nullable UIApplication *)sharedApplicationForBackgroundTask { +#elif TARGET_OS_WATCH +- (nullable NSProcessInfo *)sharedNSProcessInfoForBackgroundTask { +#else +- (nullable id)sharedApplicationForBackgroundTask { +#endif + id sharedInstance = nil; +#if TARGET_OS_IOS || TARGET_OS_TV + if (![self isAppExtension]) { + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedInstance = [uiApplicationClass sharedApplication]; + } + } +#elif TARGET_OS_WATCH + sharedInstance = [NSProcessInfo processInfo]; +#endif + return sharedInstance; +} + +#pragma mark - UIApplicationDelegate and WKExtensionDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH +- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif { + _isRunningInBackground = YES; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is backgrounding."); + [notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil]; +} + +- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif { + _isRunningInBackground = NO; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is foregrounding."); + [notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)iOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - NSApplicationDelegate + +#if TARGET_OS_OSX +- (void)macOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug(@"%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_OSX + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m new file mode 100644 index 00000000..8e8bf38b --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m @@ -0,0 +1,125 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORReachability.h" +#import "GDTCORLibrary/Private/GDTCORReachability_Private.h" + +#import + +#import + +/** Sets the _callbackFlag ivar whenever the network changes. + * + * @param reachability The reachability object calling back. + * @param flags The new flag values. + * @param info Any data that might be passed in by the callback. + */ +static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability, + GDTCORNetworkReachabilityFlags flags, + void *info); + +@implementation GDTCORReachability { + /** The reachability object. */ + GDTCORNetworkReachabilityRef _reachabilityRef; + + /** The queue on which callbacks and all work will occur. */ + dispatch_queue_t _reachabilityQueue; + + /** Flags specified by reachability callbacks. */ + GDTCORNetworkReachabilityFlags _callbackFlags; +} + ++ (void)initialize { + [self sharedInstance]; +} + ++ (instancetype)sharedInstance { + static GDTCORReachability *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORReachability alloc] init]; + }); + return sharedInstance; +} + ++ (GDTCORNetworkReachabilityFlags)currentFlags { + __block GDTCORNetworkReachabilityFlags currentFlags; +#if !TARGET_OS_WATCH + dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{ + GDTCORReachability *reachability = [GDTCORReachability sharedInstance]; + currentFlags = + reachability->_callbackFlags ? reachability->_callbackFlags : reachability->_flags; + GDTCORLogDebug(@"Initial reachability flags determined: %d", currentFlags); + }); +#else + currentFlags = kGDTCORNetworkReachabilityFlagsReachable; +#endif + return currentFlags; +} + +- (instancetype)init { + self = [super init]; +#if !TARGET_OS_WATCH + if (self) { + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + _reachabilityQueue = + dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL); + _reachabilityRef = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set."); + } + success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", + @"The reachability callback wasn't set."); + } + + // Get the initial set of flags. + dispatch_async(_reachabilityQueue, ^{ + Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags); + if (!valid) { + GDTCORLogDebug(@"%@", @"Determining reachability failed."); + self->_flags = 0; + } + }); + } +#endif + return self; +} + +- (void)setCallbackFlags:(GDTCORNetworkReachabilityFlags)flags { + if (_callbackFlags != flags) { + self->_callbackFlags = flags; + } +} + +@end + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +static void GDTCORReachabilityCallback(GDTCORNetworkReachabilityRef reachability, + GDTCORNetworkReachabilityFlags flags, + void *info) { +#pragma clang diagnostic pop + GDTCORLogDebug(@"Reachability changed, new flags: %d", flags); + [[GDTCORReachability sharedInstance] setCallbackFlags:flags]; +} diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m new file mode 100644 index 00000000..8f7cacb9 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m @@ -0,0 +1,191 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORRegistrar.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h" + +id _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target) { + return [GDTCORRegistrar sharedInstance].targetToStorage[@(target)]; +} + +@implementation GDTCORRegistrar { + /** Backing ivar for targetToUploader property. */ + NSMutableDictionary> *_targetToUploader; + + /** Backing ivar for targetToPrioritizer property. */ + NSMutableDictionary> *_targetToPrioritizer; + + /** Backing ivar for targetToStorage property. */ + NSMutableDictionary> *_targetToStorage; +} + ++ (instancetype)sharedInstance { + static GDTCORRegistrar *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORRegistrar alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _registrarQueue = dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_SERIAL); + _targetToPrioritizer = [[NSMutableDictionary alloc] init]; + _targetToUploader = [[NSMutableDictionary alloc] init]; + _targetToStorage = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)registerUploader:(id)backend target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug(@"Registered an uploader: %@ for target:%ld", backend, (long)target); + strongSelf->_targetToUploader[@(target)] = backend; + } + }); +} + +- (void)registerStorage:(id)storage target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug(@"Registered storage: %@ for target:%ld", storage, (long)target); + strongSelf->_targetToStorage[@(target)] = storage; + } + }); +} + +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug(@"Registered a prioritizer: %@ for target:%ld", prioritizer, (long)target); + strongSelf->_targetToPrioritizer[@(target)] = prioritizer; + } + }); +} + +- (NSMutableDictionary> *)targetToUploader { + __block NSMutableDictionary> *targetToUploader; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToUploader = strongSelf->_targetToUploader; + } + }); + return targetToUploader; +} + +- (NSMutableDictionary> *)targetToPrioritizer { + __block NSMutableDictionary> *targetToPrioritizer; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToPrioritizer = strongSelf->_targetToPrioritizer; + } + }); + return targetToPrioritizer; +} + +- (NSMutableDictionary> *)targetToStorage { + __block NSMutableDictionary> *targetToStorage; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToStorage = strongSelf->_targetToStorage; + } + }); + return targetToStorage; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillBackground:(nonnull GDTCORApplication *)app { + NSArray> *uploaders = [self.targetToUploader allValues]; + for (id uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillBackground:)]) { + [uploader appWillBackground:app]; + } + } + NSArray> *prioritizers = [self.targetToPrioritizer allValues]; + for (id prioritizer in prioritizers) { + if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) { + [prioritizer appWillBackground:app]; + } + } + NSArray> *storages = [self.targetToStorage allValues]; + for (id storage in storages) { + if ([storage respondsToSelector:@selector(appWillBackground:)]) { + [storage appWillBackground:app]; + } + } +} + +- (void)appWillForeground:(nonnull GDTCORApplication *)app { + NSArray> *uploaders = [self.targetToUploader allValues]; + for (id uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillForeground:)]) { + [uploader appWillForeground:app]; + } + } + NSArray> *prioritizers = [self.targetToPrioritizer allValues]; + for (id prioritizer in prioritizers) { + if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) { + [prioritizer appWillForeground:app]; + } + } + NSArray> *storages = [self.targetToStorage allValues]; + for (id storage in storages) { + if ([storage respondsToSelector:@selector(appWillForeground:)]) { + [storage appWillForeground:app]; + } + } +} + +- (void)appWillTerminate:(nonnull GDTCORApplication *)app { + NSArray> *uploaders = [self.targetToUploader allValues]; + for (id uploader in uploaders) { + if ([uploader respondsToSelector:@selector(appWillTerminate:)]) { + [uploader appWillTerminate:app]; + } + } + NSArray> *prioritizers = [self.targetToPrioritizer allValues]; + for (id prioritizer in prioritizers) { + if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) { + [prioritizer appWillTerminate:app]; + } + } + NSArray> *storages = [self.targetToStorage allValues]; + for (id storage in storages) { + if ([storage respondsToSelector:@selector(appWillTerminate:)]) { + [storage appWillTerminate:app]; + } + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m new file mode 100644 index 00000000..35f456e0 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m @@ -0,0 +1,104 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" + +#import +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +@implementation GDTCORTransformer + ++ (instancetype)sharedInstance { + static GDTCORTransformer *eventTransformer; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventTransformer = [[self alloc] init]; + }); + return eventTransformer; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _eventWritingQueue = + dispatch_queue_create("com.google.GDTCORTransformer", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(NSArray> *)transformers + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event, @"You can't write a nil event"); + BOOL hadOriginalCompletion = completion != nil; + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTTransformer" + expirationHandler:^{ + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + dispatch_async(_eventWritingQueue, ^{ + GDTCOREvent *transformedEvent = event; + for (id transformer in transformers) { + if ([transformer respondsToSelector:@selector(transform:)]) { + GDTCORLogDebug(@"Applying a transformer to event %@", event); + transformedEvent = [transformer transform:transformedEvent]; + if (!transformedEvent) { + completion(NO, nil); + return; + } + } else { + GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform, + @"Transformer doesn't implement transform: %@", transformer); + completion(NO, nil); + return; + } + } + + id storage = + [GDTCORRegistrar sharedInstance].targetToStorage[@(event.target)]; + + [storage storeEvent:transformedEvent onComplete:hadOriginalCompletion ? completion : nil]; + + // The work is done, cancel the background task if it's valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + // Flush the queue immediately. + dispatch_sync(_eventWritingQueue, ^{ + }); +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m new file mode 100644 index 00000000..6c6af23f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m @@ -0,0 +1,92 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORTransport.h" +#import "GDTCORLibrary/Private/GDTCORTransport_Private.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +@implementation GDTCORTransport + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _transformers = transformers; + _target = target; + _transformerInstance = [GDTCORTransformer sharedInstance]; + } + GDTCORLogDebug(@"Transport object created. mappingID:%@ transformers:%@ target:%ld", mappingID, + transformers, (long)target); + return self; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete: + (void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + event.qosTier = GDTCOREventQoSTelemetry; + [self sendEvent:event onComplete:completion]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please."); + [self sendEvent:event onComplete:completion]; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event { + [self sendTelemetryEvent:event onComplete:nil]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event { + [self sendDataEvent:event onComplete:nil]; +} + +- (GDTCOREvent *)eventForTransport { + return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; +} + +#pragma mark - Private helper methods + +/** Sends the given event through the transport pipeline. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion { + // TODO: Determine if sending an event before registration is allowed. + GDTCORAssert(event, @"You can't send a nil event"); + GDTCOREvent *copiedEvent = [event copy]; + copiedEvent.clockSnapshot = [GDTCORClock snapshot]; + [self.transformerInstance transformEvent:copiedEvent + withTransformers:_transformers + onComplete:completion]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m new file mode 100644 index 00000000..c712e5e6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m @@ -0,0 +1,275 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +@implementation GDTCORUploadCoordinator + ++ (instancetype)sharedInstance { + static GDTCORUploadCoordinator *sharedUploader; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedUploader = [[GDTCORUploadCoordinator alloc] init]; + [sharedUploader startTimer]; + }); + return sharedUploader; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _coordinationQueue = + dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL); + _registrar = [GDTCORRegistrar sharedInstance]; + _timerInterval = 30 * NSEC_PER_SEC; + _timerLeeway = 5 * NSEC_PER_SEC; + _targetToInFlightPackages = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)forceUploadForTarget:(GDTCORTarget)target { + dispatch_async(_coordinationQueue, ^{ + GDTCORLogDebug(@"Forcing an upload of target %ld", (long)target); + GDTCORUploadConditions conditions = [self uploadConditions]; + conditions |= GDTCORUploadConditionHighPriority; + [self uploadTargets:@[ @(target) ] conditions:conditions]; + }); +} + +#pragma mark - Private helper methods + +/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will + * check the next-upload clocks of all targets to determine if an upload attempt can be made. + */ +- (void)startTimer { + dispatch_async(_coordinationQueue, ^{ + self->_timer = + dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue); + dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval, + self->_timerLeeway); + dispatch_source_set_event_handler(self->_timer, ^{ + if (![[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORUploadConditions conditions = [self uploadConditions]; + GDTCORLogDebug(@"%@", @"Upload timer fired"); + [self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions]; + } + }); + GDTCORLogDebug(@"%@", @"Upload timer started"); + dispatch_resume(self->_timer); + }); +} + +/** Stops the currently running timer. */ +- (void)stopTimer { + if (_timer) { + dispatch_source_cancel(_timer); + } +} + +/** Triggers the uploader implementations for the given targets to upload. + * + * @param targets An array of targets to trigger. + * @param conditions The set of upload conditions. + */ +- (void)uploadTargets:(NSArray *)targets conditions:(GDTCORUploadConditions)conditions { + dispatch_async(_coordinationQueue, ^{ + if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) { + return; + } + for (NSNumber *target in targets) { + // Don't trigger uploads for targets that have an in-flight package already. + if (self->_targetToInFlightPackages[target]) { + GDTCORLogDebug(@"Target %@ will not upload, there's an upload in flight", target); + continue; + } + // Ask the uploader if they can upload and do so, if it can. + id uploader = self.registrar.targetToUploader[target]; + if ([uploader readyToUploadTarget:target.intValue conditions:conditions]) { + id prioritizer = self.registrar.targetToPrioritizer[target]; + GDTCORUploadPackage *package = [prioritizer uploadPackageWithTarget:target.intValue + conditions:conditions]; + if (package.events.count) { + self->_targetToInFlightPackages[target] = package; + GDTCORLogDebug(@"Package of %ld events is being handed over to an uploader", + (long)package.events.count); + [uploader uploadPackage:package]; + } else { + [package completeDelivery]; + } + } + GDTCORLogDebug(@"Target %@ is not ready to upload", target); + } + }); +} + +/** Returns the registered storage for the given NSNumber wrapped GDTCORTarget. + * + * @param target The NSNumber wrapping of a GDTCORTarget to find the storage instance of. + * @return The storage instance for the given target. + */ +- (nullable id)storageForTarget:(NSNumber *)target { + id storage = [GDTCORRegistrar sharedInstance].targetToStorage[target]; + GDTCORAssert(storage, @"A storage must be registered for target %@", target); + return storage; +} + +/** Returns the current upload conditions after making determinations about the network connection. + * + * @return The current upload conditions. + */ +- (GDTCORUploadConditions)uploadConditions { + GDTCORNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags]; + BOOL networkConnected = GDTCORReachabilityFlagsReachable(currentFlags); + if (!networkConnected) { + return GDTCORUploadConditionNoNetwork; + } + BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags); + if (isWWAN) { + return GDTCORUploadConditionMobileData; + } else { + return GDTCORUploadConditionWifiData; + } +} + +#pragma mark - NSSecureCoding support + +/** The NSKeyedCoder key for the targetToInFlightPackages property. */ +static NSString *const ktargetToInFlightPackagesKey = + @"GDTCORUploadCoordinatortargetToInFlightPackages"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + GDTCORUploadCoordinator *sharedCoordinator = [GDTCORUploadCoordinator sharedInstance]; + dispatch_sync(sharedCoordinator->_coordinationQueue, ^{ + @try { + NSSet *classes = + [NSSet setWithObjects:[NSMutableDictionary class], [GDTCORUploadPackage class], nil]; + sharedCoordinator->_targetToInFlightPackages = + [aDecoder decodeObjectOfClasses:classes forKey:ktargetToInFlightPackagesKey]; + + } @catch (NSException *exception) { + sharedCoordinator->_targetToInFlightPackages = [NSMutableDictionary dictionary]; + } + }); + return sharedCoordinator; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + dispatch_sync(_coordinationQueue, ^{ + // All packages that have been given to uploaders need to be tracked so that their expiration + // timers can be called. + if (self->_targetToInFlightPackages.count > 0) { + [aCoder encodeObject:self->_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey]; + } + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + // -startTimer is thread-safe. + [self startTimer]; +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + NSSet *packageEvents = [package.events copy]; + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + if (!prioritizer) { + GDTCORLogError(GDTCORMCEPrioritizerError, + @"A prioritizer should be registered for this target: %@", targetNumber); + } + if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) { + [prioritizer packageDelivered:[package copy] successful:successful]; + } + } + if (successful && packageEvents.count) { + NSMutableSet *eventIDs = [[NSMutableSet alloc] init]; + for (GDTCOREvent *event in packageEvents) { + NSNumber *eventID = event.eventID; + if (eventID != nil) { + [eventIDs addObject:eventID]; + } else { + GDTCORLogDebug(@"An event was missing its ID: %@", event); + } + } + [[self storageForTarget:@(package.target)] removeEvents:eventIDs]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + id uploader = registrar.targetToUploader[targetNumber]; + if ([prioritizer respondsToSelector:@selector(packageExpired:)]) { + [prioritizer packageExpired:package]; + } + if ([uploader respondsToSelector:@selector(packageExpired:)]) { + [uploader packageExpired:package]; + } + } + }); +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m new file mode 100644 index 00000000..38b7a7c5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m @@ -0,0 +1,193 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORUploadPackage.h" + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +/** A class that holds a weak reference to an upload package, for use by the package's NSTimer. */ +@interface GDTCORUploadPackageTimerHolder : NSObject + +/** The upload package. */ +@property(weak, nonatomic) GDTCORUploadPackage *package; + +@end + +@implementation GDTCORUploadPackageTimerHolder + +/** Calls checkIfPackageIsExpired on the package if non-nil. Invalidates if the package is nil. + * + * @param timer The timer instance calling this method. + */ +- (void)timerFired:(NSTimer *)timer { + if (_package) { + [_package checkIfPackageIsExpired]; + } else { + [timer invalidate]; + } +} + +@end + +@implementation GDTCORUploadPackage { + /** If YES, the package's -completeDelivery method has been called. */ + BOOL _isDelivered; + + /** If YES, is being handled by the handler. */ + BOOL _isHandled; + + /** A timer that will regularly check to see whether this package has expired or not. */ + NSTimer *_expirationTimer; +} + +- (instancetype)initWithTarget:(GDTCORTarget)target { + self = [super init]; + if (self) { + _target = target; + _storage = [GDTCORRegistrar sharedInstance].targetToStorage[@(target)]; + _deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000]; + _handler = [GDTCORUploadCoordinator sharedInstance]; + GDTCORUploadPackageTimerHolder *holder = [[GDTCORUploadPackageTimerHolder alloc] init]; + holder.package = self; + _expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 + target:holder + selector:@selector(timerFired:) + userInfo:nil + repeats:YES]; + } + GDTCORLogDebug(@"Upload package created %@", self); + return self; +} + +- (instancetype)copy { + GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] init]; + newPackage->_target = _target; + newPackage->_storage = _storage; + newPackage->_deliverByTime = _deliverByTime; + newPackage->_handler = _handler; + GDTCORUploadPackageTimerHolder *holder = [[GDTCORUploadPackageTimerHolder alloc] init]; + holder.package = newPackage; + newPackage->_expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 + target:holder + selector:@selector(timerFired:) + userInfo:nil + repeats:YES]; + newPackage->_events = [_events copy]; + GDTCORLogDebug(@"Copying UploadPackage %@ to %@", self, newPackage); + return newPackage; +} + +- (NSUInteger)hash { + return [_events hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (void)dealloc { + [_expirationTimer invalidate]; +} + +- (void)completeDelivery { + if (_isDelivered) { + GDTCORLogError(GDTCORMCEDeliverTwice, @"%@", + @"It's an API violation to call -completeDelivery twice."); + } + _isDelivered = YES; + [_expirationTimer invalidate]; + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + _isHandled = YES; + [_handler packageDelivered:[self copy] successful:YES]; + } + GDTCORLogDebug(@"Upload package delivered: %@", self); +} + +- (void)retryDeliveryInTheFuture { + [_expirationTimer invalidate]; + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + _isHandled = YES; + [_handler packageDelivered:[self copy] successful:NO]; + } + GDTCORLogDebug(@"Upload package will retry in the future: %@", self); +} + +- (void)checkIfPackageIsExpired { + if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) { + [_expirationTimer invalidate]; + if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) { + _isHandled = YES; + GDTCORLogDebug(@"Upload package expired: %@", self); + [_handler packageExpired:self]; + } + } +} + +#pragma mark - NSSecureCoding + +/** The keyed archiver key for the events property. */ +static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey"; + +/** The keyed archiver key for the _isHandled property. */ +static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey"; + +/** The keyed archiver key for the _isHandled ivar. */ +static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey"; + +/** The keyed archiver key for the handler property. */ +static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey"; + +/** The keyed archiver key for the target property. */ +static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_events forKey:kEventsKey]; + [aCoder encodeObject:_deliverByTime forKey:kDeliverByTimeKey]; + [aCoder encodeBool:_isHandled forKey:kIsHandledKey]; + [aCoder encodeObject:_handler forKey:kHandlerKey]; + [aCoder encodeInteger:_target forKey:kTargetKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + // Sets a global translation mapping to decode GDTCORStoredEvent objects encoded as instances of + // GDTCOREvent instead. + [NSKeyedUnarchiver setClass:[GDTCOREvent class] forClassName:@"GDTCORStoredEvent"]; + + GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey]; + self = [self initWithTarget:target]; + if (self) { + NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCOREvent class], nil]; + _events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey]; + _deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey]; + _isHandled = [aDecoder decodeBoolForKey:kIsHandledKey]; + // _handler isn't technically NSSecureCoding, because we don't know the class of this object. + // but it gets decoded anyway. + } + return self; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORDataFuture.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORDataFuture.h new file mode 100644 index 00000000..685cf2ba --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORDataFuture.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class represents a future data object, determined at instantiation time. */ +@interface GDTCORDataFuture : NSObject + +/** If not nil, this data future was instantiated with this file URL. */ +@property(nullable, readonly, nonatomic) NSURL *fileURL; + +/** Initializes an instance with the given the fileURL. + * + * @param fileURL The fileURL containing the data to return in -data. + * @return An instance of this class. + */ +- (instancetype)initWithFileURL:(NSURL *)fileURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h new file mode 100644 index 00000000..485d6bb8 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCOREvent () + +/** The unique ID of the event. This property is for testing only. */ +@property(nonatomic, readwrite) NSNumber *eventID; + +/** The GDT relative file path of the event. */ +@property(nullable, nonatomic, readonly) NSString *GDTFilePath; + +/** Writes [dataObject transportBytes] to the given URL, populates fileURL with the filename, then + * nils the dataObject property. This method should not be called twice on the same event. + * + * @param filePath The GDTCORRootDirectory-relative path that dataObject will be written to. + * @param error If populated, the error encountered during writing to disk. + * @return YES if writing dataObject to disk was successful, NO otherwise. + */ +- (BOOL)writeToGDTPath:(NSString *)filePath error:(NSError **)error; + +/** Generates incrementing event IDs, stored in a file in the app's cache. + * + * @return An event ID that is incremented based on a number in a file stored in the app cache. + */ ++ (NSNumber *)nextEventID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h new file mode 100644 index 00000000..837c3ea0 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h @@ -0,0 +1,59 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +@class GDTCOREvent; +@class GDTCORUploadCoordinator; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the storage of events. This class is thread-safe. */ +@interface GDTCORFlatFileStorage + : NSObject + +/** The queue on which all storage work will occur. */ +@property(nonatomic) dispatch_queue_t storageQueue; + +/** A map of targets to a set of stored events. */ +@property(nonatomic) + NSMutableDictionary *> *targetToEventSet; + +/** All the events that have been stored. */ +@property(readonly, nonatomic) NSMutableDictionary *storedEvents; + +/** The upload coordinator instance used by this storage instance. */ +@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator; + +/** Creates and/or returns the storage singleton. + * + * @return The storage singleton. + */ ++ (instancetype)sharedInstance; + +/** Returns the path to the keyed archive of the singleton. This is where the singleton is saved + * to disk during certain app lifecycle events. + * + * @return File path to serialized singleton. + */ ++ (NSString *)archivePath; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h new file mode 100644 index 00000000..c5ca191a --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORReachability.h" + +@interface GDTCORReachability () + +/** Allows manually setting the flags for testing purposes. */ +@property(nonatomic, readwrite) GDTCORNetworkReachabilityFlags flags; + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h new file mode 100644 index 00000000..8b298397 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GDTCORRegistrar () + +NS_ASSUME_NONNULL_BEGIN + +/** The concurrent queue on which all registration occurs. */ +@property(nonatomic, readonly) dispatch_queue_t registrarQueue; + +/** A map of targets to backend implementations. */ +@property(atomic, readonly) NSMutableDictionary> *targetToUploader; + +/** A map of targets to prioritizer implementations. */ +@property(atomic, readonly) + NSMutableDictionary> *targetToPrioritizer; + +/** A map of targets to storage instances. */ +@property(atomic, readonly) + NSMutableDictionary> *targetToStorage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h new file mode 100644 index 00000000..e2dbff12 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +@protocol GDTCOREventTransformer; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the transforming of events. It's desirable for this to be its own class + * because running all events through a single instance ensures that transformers are thread-safe. + * Having a per-transport queue to run on isn't sufficient because transformer objects could + * maintain state (or at least, there's nothing to stop them from doing that) and the same instances + * may be used across multiple instances. + */ +@interface GDTCORTransformer : NSObject + +/** Instantiates or returns the event transformer singleton. + * + * @return The singleton instance of the event transformer. + */ ++ (instancetype)sharedInstance; + +/** Writes the result of applying the given transformers' -transform method on the given event. + * + * @note If the app is suspended, a background task will be created to complete work in-progress, + * but this method will not send any further events until the app is resumed. + * + * @param event The event to apply transformers on. + * @param transformers The list of transformers to apply. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(nullable NSArray> *)transformers + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h new file mode 100644 index 00000000..4adcf93e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransformer () + +/** The queue on which all work will occur. */ +@property(nonatomic) dispatch_queue_t eventWritingQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h new file mode 100644 index 00000000..71f73a6f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCORTransformer; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport () + +/** The mapping identifier that the target backend will use to map the transport bytes to proto. */ +@property(nonatomic) NSString *mappingID; + +/** The transformers that will operate on events sent by this transport. */ +@property(nonatomic) NSArray> *transformers; + +/** The target backend of this transport. */ +@property(nonatomic) NSInteger target; + +/** The transformer instance to used to transform events. Allows injecting a fake during testing. */ +@property(nonatomic) GDTCORTransformer *transformerInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h new file mode 100644 index 00000000..b678ef25 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +@class GDTCORClock; + +NS_ASSUME_NONNULL_BEGIN + +/** This class connects storage and uploader implementations, providing events to an uploader + * and informing the storage what events were successfully uploaded or not. + */ +@interface GDTCORUploadCoordinator + : NSObject + +/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */ +/** Creates and/or returrns the singleton. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** The queue on which all upload coordination will occur. */ +@property(nonatomic, readonly) dispatch_queue_t coordinationQueue; + +/** A timer that will causes regular checks for events to upload. */ +@property(nonatomic, readonly) dispatch_source_t timer; + +/** The interval the timer will fire. */ +@property(nonatomic, readonly) uint64_t timerInterval; + +/** Some leeway given to libdispatch for the timer interval event. */ +@property(nonatomic, readonly) uint64_t timerLeeway; + +/** The map of targets to in-flight packages. */ +@property(nonatomic, readonly) + NSMutableDictionary *targetToInFlightPackages; + +/** The registrar object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORRegistrar *registrar; + +/** Forces the backend specified by the target to upload the provided set of events. This should + * only ever happen when the QoS tier of an event requires it. + * + * @param target The target that should force an upload. + */ +- (void)forceUploadForTarget:(GDTCORTarget)target; + +/** Starts the upload timer. */ +- (void)startTimer; + +/** Stops the upload timer from running. */ +- (void)stopTimer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h new file mode 100644 index 00000000..1ab64325 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GDTCORUploadPackage () + +/** The storage object this upload package will use to resolve event hashes to files. */ +@property(nonatomic) id storage; + +/** A handler that will receive callbacks for certain events. */ +@property(nonatomic) id handler; + +/** Checks if the package is expired and calls -packageExpired: on the handler if necessary. */ +- (void)checkIfPackageIsExpired; + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h new file mode 100644 index 00000000..c0f9712c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A block type that could be run instead of normal assertion logging. No return type, no params. + */ +typedef void (^GDTCORAssertionBlock)(void); + +/** Returns the result of executing a soft-linked method present in unit tests that allows a block + * to be run instead of normal assertion logging. This helps ameliorate issues with catching + * exceptions that occur on a dispatch_queue. + * + * @return A block that can be run instead of normal assert printing. + */ +FOUNDATION_EXPORT GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void); + +#if defined(NS_BLOCK_ASSERTIONS) + +#define GDTCORAssert(condition, ...) \ + do { \ + } while (0); + +#define GDTCORFatalAssert(condition, ...) \ + do { \ + } while (0); + +#else // defined(NS_BLOCK_ASSERTIONS) + +/** Asserts using a console log, unless a block was specified to be run instead. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORAssert(condition, format, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogAssert(NO, __assert_file__, __LINE__, format, ##__VA_ARGS__); \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not + * defined. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORFatalAssert(condition, format, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogAssert(YES, __assert_file__, __LINE__, format, ##__VA_ARGS__); \ + [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ + object:self \ + file:__assert_file__ \ + lineNumber:__LINE__ \ + description:format, ##__VA_ARGS__]; \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +#endif // defined(NS_BLOCK_ASSERTIONS) + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h new file mode 100644 index 00000000..01de21ae --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class manages the device clock and produces snapshots of the current time. */ +@interface GDTCORClock : NSObject + +/** The wallclock time, UTC, in milliseconds. */ +@property(nonatomic, readonly) int64_t timeMillis; + +/** The offset from UTC in seconds. */ +@property(nonatomic, readonly) int64_t timezoneOffsetSeconds; + +/** The kernel boot time when this clock was created. */ +@property(nonatomic, readonly) int64_t kernelBootTime; + +/** The device uptime when this clock was created. */ +@property(nonatomic, readonly) int64_t uptime; + +/** Creates a GDTCORClock object using the current time and offsets. + * + * @return A new GDTCORClock object representing the current time state. + */ ++ (instancetype)snapshot; + +/** Creates a GDTCORClock object representing a time in the future, relative to now. + * + * @param millisInTheFuture The millis in the future from now this clock should represent. + * @return An instance representing a future time. + */ ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture; + +/** Compares one clock with another, returns YES if the caller is after the parameter. + * + * @return YES if the calling clock's time is after the given clock's time. + */ +- (BOOL)isAfter:(GDTCORClock *)otherClock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h new file mode 100644 index 00000000..d306f182 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h @@ -0,0 +1,143 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The current logging level. This value and higher will be printed. Declared as volatile to make + * getting and setting atomic. + */ +FOUNDATION_EXPORT volatile NSInteger GDTCORConsoleLoggerLoggingLevel; + +/** A list of logging levels that GDT supports. */ +typedef NS_ENUM(NSInteger, GDTCORLoggingLevel) { + + /** Causes all logs to be printed. */ + GDTCORLoggingLevelDebug = 1, + + /** Causes all non-debug logs to be printed. */ + GDTCORLoggingLevelVerbose = 2, + + /** Causes warnings and errors to be printed. */ + GDTCORLoggingLevelWarnings = 3, + + /** Causes errors to be printed. This is the default value. */ + GDTCORLoggingLevelErrors = 4 +}; + +/** A list of message codes to print in the logger that help to correspond printed messages with + * code locations. + * + * Prefixes: + * - MCD => MessageCodeDebug + * - MCW => MessageCodeWarning + * - MCE => MessageCodeError + */ +typedef NS_ENUM(NSInteger, GDTCORMessageCode) { + + /** For debug logs. */ + GDTCORMCDDebugLog = 0, + + /** For warning messages concerning transportBytes: not being implemented by a data object. */ + GDTCORMCWDataObjectMissingBytesImpl = 1, + + /** For warning messages concerning a failed event upload. */ + GDTCORMCWUploadFailed = 2, + + /** For warning messages concerning a forced event upload. */ + GDTCORMCWForcedUpload = 3, + + /** For warning messages concerning a failed reachability call. */ + GDTCORMCWReachabilityFailed = 4, + + /** For warning messages concerning a database warning. */ + GDTCORMCWDatabaseWarning = 5, + + /** For warning messages concerning the reading of a event file. */ + GDTCORMCWFileReadError = 6, + + /** For error messages concerning transform: not being implemented by an event transformer. */ + GDTCORMCETransformerDoesntImplementTransform = 1000, + + /** For error messages concerning the creation of a directory failing. */ + GDTCORMCEDirectoryCreationError = 1001, + + /** For error messages concerning the writing of a event file. */ + GDTCORMCEFileWriteError = 1002, + + /** For error messages concerning the lack of a prioritizer for a given backend. */ + GDTCORMCEPrioritizerError = 1003, + + /** For error messages concerning a package delivery API violation. */ + GDTCORMCEDeliverTwice = 1004, + + /** For error messages concerning an error in an implementation of -transportBytes. */ + GDTCORMCETransportBytesError = 1005, + + /** For general purpose error messages in a dependency. */ + GDTCORMCEGeneralError = 1006, + + /** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open + * an issue if you encounter an error with this code. + */ + GDTCORMCEFatalAssertion = 1007, + + /** For error messages concerning the reading of a event file. */ + GDTCORMCEFileReadError = 1008, + + /** For errors related to running sqlite. */ + GDTCORMCEDatabaseError = 1009, +}; + +/** Prints the given code and format string to the console. + * + * @param code The message code describing the nature of the log. + * @param logLevel The log level of this log. + * @param format The format string. + */ +FOUNDATION_EXPORT +void GDTCORLog(GDTCORMessageCode code, GDTCORLoggingLevel logLevel, NSString *_Nonnull format, ...) + NS_FORMAT_FUNCTION(3, 4); + +/** Prints an assert log to the console. + * + * @param wasFatal Send YES if the assertion should be fatal, NO otherwise. + * @param file The file in which the failure occurred. + * @param line The line number of the failure. + * @param format The format string. + */ +FOUNDATION_EXPORT void GDTCORLogAssert(BOOL wasFatal, + NSString *_Nonnull file, + NSInteger line, + NSString *_Nullable format, + ...) NS_FORMAT_FUNCTION(4, 5); + +/** Returns the string that represents some message code. + * + * @param code The code to convert to a string. + * @return The string representing the message code. + */ +FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code); + +#define GDTCORLogDebug(MESSAGE_FORMAT, ...) \ + GDTCORLog(GDTCORMCDDebugLog, GDTCORLoggingLevelDebug, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogWarning with slightly more convenient usage. +#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelWarnings, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogError with slightly more convenient usage and a failing assert. +#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, GDTCORLoggingLevelErrors, MESSAGE_FORMAT, __VA_ARGS__); diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h new file mode 100644 index 00000000..4d6ffce6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h @@ -0,0 +1,89 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCORClock; + +NS_ASSUME_NONNULL_BEGIN + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCOREventQoS) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCOREventQoSUnknown = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCOREventQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCOREventQoSDaily = 2, + + /** This event should be sent when requested by the uploader. */ + GDTCOREventQosDefault = 3, + + /** This event should be sent immediately along with any other data that can be batched. */ + GDTCOREventQoSFast = 4, + + /** This event should only be uploaded on wifi. */ + GDTCOREventQoSWifiOnly = 5, +}; + +@interface GDTCOREvent : NSObject + +/** The unique ID of the event. */ +@property(nonatomic, readonly) NSNumber *eventID; + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) NSInteger target; + +/** The data object encapsulated in the transport of your choice, as long as it implements + * the GDTCOREventDataObject protocol. */ +@property(nullable, nonatomic) id dataObject; + +/** The quality of service tier this event belongs to. */ +@property(nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(nonatomic) GDTCORClock *clockSnapshot; + +/** The resulting file URL when [dataObject -transportBytes] has been saved to disk.*/ +@property(nullable, readonly, nonatomic) NSURL *fileURL; + +/** Bytes that can be used by a prioritizer or uploader later on. It's the prioritizer or uploader's + * responsibility to serialize and deserialize these bytes. + */ +@property(nullable, nonatomic) NSData *customBytes; + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes an instance using the given mappingID. + * + * @param mappingID The mapping identifier. + * @param target The event's target identifier. + * @return An instance of this class. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h new file mode 100644 index 00000000..34ef6242 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface that event protos should implement regardless of the + * underlying transport technology (protobuf, nanopb, etc). + */ +@protocol GDTCOREventDataObject + +@required + +/** Returns the serialized proto bytes of the implementing event proto. + * + * @return the serialized proto bytes of the implementing event proto. + */ +- (NSData *)transportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h new file mode 100644 index 00000000..29f95924 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Defines the API that event transformers must adopt. */ +@protocol GDTCOREventTransformer + +@required + +/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in + * instances where the event should be sampled. + * + * @param event The event to transform. + * @return A transformed event, or nil if the transformation dropped the event. + */ +- (nullable GDTCOREvent *)transform:(GDTCOREvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h new file mode 100644 index 00000000..a08a4569 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** A protocol defining the lifecycle events objects in the library must respond to immediately. */ +@protocol GDTCORLifecycleProtocol + +@optional + +/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has + * been called. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillTerminate:(GDTCORApplication *)app; + +/** Indicates that the app is moving to background and eventual suspension or the current UIScene is + * deactivating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillBackground:(GDTCORApplication *)app; + +/** Indicates that the app is resuming operation or a UIScene is activating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillForeground:(GDTCORApplication *)app; + +@end + +/** This class manages the library's response to app lifecycle events. + * + * When backgrounding, the library doesn't stop processing events, it's just that several background + * tasks will end up being created for every event that's sent, and the stateful objects of the + * library (GDTCORStorage and GDTCORUploadCoordinator instances) will deserialize themselves from + * and to disk before and after every operation, respectively. + */ +@interface GDTCORLifecycle : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h new file mode 100644 index 00000000..97bd0835 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h @@ -0,0 +1,204 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if !TARGET_OS_WATCH +#import +#endif + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#elif TARGET_OS_WATCH +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** The GoogleDataTransport library version. */ +FOUNDATION_EXPORT NSString *const kGDTCORVersion; + +/** A notification sent out if the app is backgrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification; + +/** A notification sent out if the app is foregrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification; + +/** A notification sent out if the app is terminating. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification; + +/** The different possible network connection type. */ +typedef NS_ENUM(NSInteger, GDTCORNetworkType) { + GDTCORNetworkTypeUNKNOWN = 0, + GDTCORNetworkTypeWIFI = 1, + GDTCORNetworkTypeMobile = 2, +}; + +/** The different possible network connection mobile subtype. */ +typedef NS_ENUM(NSInteger, GDTCORNetworkMobileSubtype) { + GDTCORNetworkMobileSubtypeUNKNOWN = 0, + GDTCORNetworkMobileSubtypeGPRS = 1, + GDTCORNetworkMobileSubtypeEdge = 2, + GDTCORNetworkMobileSubtypeWCDMA = 3, + GDTCORNetworkMobileSubtypeHSDPA = 4, + GDTCORNetworkMobileSubtypeHSUPA = 5, + GDTCORNetworkMobileSubtypeCDMA1x = 6, + GDTCORNetworkMobileSubtypeCDMAEVDORev0 = 7, + GDTCORNetworkMobileSubtypeCDMAEVDORevA = 8, + GDTCORNetworkMobileSubtypeCDMAEVDORevB = 9, + GDTCORNetworkMobileSubtypeHRPD = 10, + GDTCORNetworkMobileSubtypeLTE = 11, +}; + +#if !TARGET_OS_WATCH +/** Define SCNetworkReachabilityFlags as GDTCORNetworkReachabilityFlags on non-watchOS. */ +typedef SCNetworkReachabilityFlags GDTCORNetworkReachabilityFlags; + +/** Define SCNetworkReachabilityRef as GDTCORNetworkReachabilityRef on non-watchOS. */ +typedef SCNetworkReachabilityRef GDTCORNetworkReachabilityRef; + +#else +/** The different possible reachabilityFlags option on watchOS. */ +typedef NS_OPTIONS(uint32_t, GDTCORNetworkReachabilityFlags) { + kGDTCORNetworkReachabilityFlagsReachable = 1 << 1, + // TODO(doudounan): Add more options on watchOS if watchOS network connection information relative + // APIs available in the future. +}; + +/** Define a struct as GDTCORNetworkReachabilityRef on watchOS to store network connection + * information. */ +typedef struct { + // TODO(doudounan): Store network connection information on watchOS if watchOS network connection + // information relative APIs available in the future. +} GDTCORNetworkReachabilityRef; +#endif + +/** Returns a URL to the root directory under which all GDT-associated data must be saved. + * + * @return A URL to the root directory under which all GDT-associated data must be saved. + */ +NSURL *GDTCORRootDirectory(void); + +/** Compares flags with the reachable flag (on non-watchos with both reachable and + * connectionRequired flags), if available, and returns YES if network reachable. + * + * @param flags The set of reachability flags. + * @return YES if the network is reachable, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsReachable(GDTCORNetworkReachabilityFlags flags); + +/** Compares flags with the WWAN reachability flag, if available, and returns YES if present. + * + * @param flags The set of reachability flags. + * @return YES if the WWAN flag is set, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsContainWWAN(GDTCORNetworkReachabilityFlags flags); + +/** Generates an enum message GDTCORNetworkType representing network connection type. + * + * @return A GDTCORNetworkType representing network connection type. + */ +GDTCORNetworkType GDTCORNetworkTypeMessage(void); + +/** Generates an enum message GDTCORNetworkMobileSubtype representing network connection mobile + * subtype. + * + * @return A GDTCORNetworkMobileSubtype representing network connection mobile subtype. + */ +GDTCORNetworkMobileSubtype GDTCORNetworkMobileSubTypeMessage(void); + +/** Writes the given object to the given fileURL and populates the given error if it fails. + * + * @param obj The object to encode. + * @param filePath The path to write the object to. Can be nil if you just need the data. + * @param error The error to populate if something goes wrong. + * @return The data of the archive. If error is nil, it's been written to disk. + */ +NSData *_Nullable GDTCOREncodeArchive(id obj, + NSString *_Nullable filePath, + NSError *_Nullable *error); + +/** Decodes an object of the given class from the given archive path or data and populates the given + * error if it fails. + * + * @param archiveClass The class of the archive's root object. + * @param archivePath The path to the archived data. Don't use with the archiveData param. + * @param archiveData The data to decode. Don't use with the archivePath param. + * @param error The error to populate if something goes wrong. + */ +id _Nullable GDTCORDecodeArchive(Class archiveClass, + NSString *_Nullable archivePath, + NSData *_Nullable archiveData, + NSError *_Nullable *error); + +/** A typedef identify background identifiers. */ +typedef volatile NSUInteger GDTCORBackgroundIdentifier; + +/** A background task's invalid sentinel value. */ +FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid; + +#if TARGET_OS_IOS || TARGET_OS_TV +/** A protocol that wraps UIApplicationDelegate, WKExtensionDelegate or NSObject protocol, depending + * on the platform. + */ +@protocol GDTCORApplicationDelegate +#elif TARGET_OS_OSX +@protocol GDTCORApplicationDelegate +#elif TARGET_OS_WATCH +@protocol GDTCORApplicationDelegate +#else +@protocol GDTCORApplicationDelegate +#endif // TARGET_OS_IOS || TARGET_OS_TV + +@end + +/** A cross-platform application class. */ +@interface GDTCORApplication : NSObject + +/** Flag to determine if the application is running in the background. */ +@property(atomic, readonly) BOOL isRunningInBackground; + +/** Creates and/or returns the shared application instance. + * + * @return The shared application instance. + */ ++ (nullable GDTCORApplication *)sharedApplication; + +/** Creates a background task with the returned identifier if on a suitable platform. + * + * @name name The name of the task, useful for debugging which background tasks are running. + * @param handler The handler block that is called if the background task expires. + * @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one + * couldn't be created. + */ +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^__nullable)(void))handler; + +/** Ends the background task if the identifier is valid. + * + * @param bgID The background task to end. + */ +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h new file mode 100644 index 00000000..d1f67549 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Options that define a set of upload conditions. This is used to help minimize end user data + * consumption impact. + */ +typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) { + + /** An upload shouldn't be attempted, because there's no network. */ + GDTCORUploadConditionNoNetwork = 1 << 0, + + /** An upload would likely use mobile data. */ + GDTCORUploadConditionMobileData = 1 << 1, + + /** An upload would likely use wifi data. */ + GDTCORUploadConditionWifiData = 1 << 2, + + /** An upload uses some sort of network connection, but it's unclear which. */ + GDTCORUploadConditionUnclearConnection = 1 << 3, + + /** A high priority event has occurred. */ + GDTCORUploadConditionHighPriority = 1 << 4, +}; + +/** This protocol defines the common interface of event prioritization. Prioritizers are + * stateful objects that prioritize events upon insertion into storage and remain prepared to return + * a set of filenames to the storage system. + */ +@protocol GDTCORPrioritizer + +@required + +/** Accepts an event and uses the event metadata to make choices on how to prioritize the event. + * This method exists as a way to help prioritize which events should be sent, which is dependent on + * the request proto structure of your backend. + * + * @param event The event to prioritize. + */ +- (void)prioritizeEvent:(GDTCOREvent *)event; + +/** Returns a set of events to upload given a set of conditions. + * + * @param target The target to create an upload package for. + * @param conditions A bit mask specifying the current upload conditions. + * @return An object to be used by the uploader to determine file URLs to upload with respect to the + * current conditions. + */ +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions; + +@optional + +/** Saves the state of the prioritizer. */ +- (void)saveState; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORReachability.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORReachability.h new file mode 100644 index 00000000..a74e311b --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORReachability.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class helps determine upload conditions by determining connectivity. */ +@interface GDTCORReachability : NSObject + +/** The current set flags indicating network conditions */ ++ (GDTCORNetworkReachabilityFlags)currentFlags; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h new file mode 100644 index 00000000..63f82a72 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the registration of targets with the transport SDK. */ +@interface GDTCORRegistrar : NSObject + +/** Creates and/or returns the singleton instance. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** Registers a backend implementation with the GoogleDataTransport infrastructure. + * + * @param backend The backend object to register. + * @param target The target this backend object will be responsible for. + */ +- (void)registerUploader:(id)backend target:(GDTCORTarget)target; + +/** Registers a storage implementation with the GoogleDataTransport infrastructure. + * + * @param storage The storage instance to be associated with this uploader and target. + * @param target The target this backend object will be responsible for. + */ +- (void)registerStorage:(id)storage target:(GDTCORTarget)target; + +/** Registers a event prioritizer implementation with the GoogleDataTransport infrastructure. + * + * @param prioritizer The prioritizer object to register. + * @param target The target this prioritizer object will be responsible for. + */ +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h new file mode 100644 index 00000000..3cc175e4 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h @@ -0,0 +1,78 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Defines the interface a storage subsystem is expected to implement. */ +@protocol GDTCORStorageProtocol + +@required + +/** Stores an event and calls onComplete with a non-nil error if anything went wrong. + * + * @param event The event to store + * @param completion The completion block to call after an attempt to store the event has been made. + */ +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Removes the events from storage. */ +- (void)removeEvents:(NSSet *)eventIDs; + +/** Persists the given data with the given key. + * + * @param data The data to store. + * @param key The unique key to store it to. + * @param onComplete An block to be run when storage of the data is complete. + */ +- (void)storeLibraryData:(NSData *)data + forKey:(NSString *)key + onComplete:(void (^)(NSError *_Nullable error))onComplete; + +/** Retrieves the stored data for the given key. + * + * @param key The key corresponding to the desired data. + * @param onComplete The callback to invoke with the data once it's retrieved. + */ +- (void)libraryDataForKey:(NSString *)key + onComplete:(void (^)(NSData *_Nullable data, NSError *_Nullable error))onComplete; + +/** Removes data from storage and calls the callback when complete. + * + * @param key The key of the data to remove. + * @param onComplete The callback that will be invoked when removing the data is complete. + */ +- (void)removeLibraryDataForKey:(NSString *)key + onComplete:(void (^)(NSError *_Nullable error))onComplete; + +@end + +/** Retrieves the storage instance for the given target. + * + * @param target The target. + * * @return The storage instance registered for the target, or nil if there is none. + */ +FOUNDATION_EXPORT +id _Nullable GDTCORStorageInstanceForTarget(GDTCORTarget target); + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h new file mode 100644 index 00000000..5db8852e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The list of targets supported by the shared transport infrastructure. If adding a new target, + * please use the previous value +1. + */ +typedef NS_ENUM(NSInteger, GDTCORTarget) { + + /** A target only used in testing. */ + kGDTCORTargetTest = 999, + + /** The CCT target. */ + kGDTCORTargetCCT = 1000, + + /** The FLL target. */ + kGDTCORTargetFLL = 1001, + + /** The CSH target. The CSH target is a special-purpose backend. Please do not use it without + * permission. + */ + kGDTCORTargetCSH = 1002 +}; diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h new file mode 100644 index 00000000..445ff728 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport : NSObject + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes a new transport that will send events to the given target backend. + * + * @param mappingID The mapping identifier used by the backend to map the data object transport + * bytes to a proto. + * @param transformers A list of transformers to be applied to events that are sent. + * @param target The target backend of this transport. + * @return A transport that will send events. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^_Nullable)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendDataEvent:(GDTCOREvent *)event; + +/** Creates an event for use by this transport. + * + * @return An event that is suited for use by this transport. + */ +- (GDTCOREvent *)eventForTransport; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h new file mode 100644 index 00000000..4f1d9daf --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class GDTCORClock; +@class GDTCOREvent; +@class GDTCORUploadPackage; + +/** A protocol that allows a handler to respond to package lifecycle events. */ +@protocol GDTCORUploadPackageProtocol + +@optional + +/** Indicates that the package has expired. + * + * @note Package expiration will only be checked every 5 seconds. + * + * @param package The package that has expired. + */ +- (void)packageExpired:(GDTCORUploadPackage *)package; + +/** Indicates that the package was successfully delivered. + * + * @param package The package that was delivered. + */ +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful; + +@end + +/** This class is a container that's handed off to uploaders. */ +@interface GDTCORUploadPackage : NSObject + +/** The set of stored events in this upload package. */ +@property(nonatomic) NSSet *events; + +/** The expiration time. If [[GDTCORClock snapshot] isAfter:deliverByTime] this package has expired. + * + * @note By default, the expiration time will be 3 minutes from creation. + */ +@property(nonatomic) GDTCORClock *deliverByTime; + +/** The target of this package. */ +@property(nonatomic, readonly) GDTCORTarget target; + +/** Initializes a package instance. + * + * @param target The target/destination of this package. + * @return An instance of this class. + */ +- (instancetype)initWithTarget:(GDTCORTarget)target; + +/** Completes delivery of the package. + * + * @note This *needs* to be called by an uploader for the package to not expire. + */ +- (void)completeDelivery; + +/** Sends the package back, indicating that delivery should be attempted again in the future. */ +- (void)retryDeliveryInTheFuture; + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h new file mode 100644 index 00000000..cadee478 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface for uploader implementations. */ +@protocol GDTCORUploader + +@required + +/** Returns YES if the uploader can make an upload attempt, NO otherwise. + * + * @param target The target being checked. + * @param conditions The conditions that the upload attempt is likely to occur under. + * @return YES if the uploader can make an upload attempt, NO otherwise. + */ +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions; + +/** Uploads events to the backend using this specific backend's chosen format. + * + * @param package The event package to upload. Make sure to call -completeDelivery. + */ +- (void)uploadPackage:(GDTCORUploadPackage *)package; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h new file mode 100644 index 00000000..a02451ad --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORRegistrar.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploadPackage.h" +#import "GDTCORUploader.h" diff --git a/MyExperiences copy/Pods/GoogleDataTransport/LICENSE b/MyExperiences copy/Pods/GoogleDataTransport/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/GoogleDataTransport/README.md b/MyExperiences copy/Pods/GoogleDataTransport/README.md new file mode 100644 index 00000000..a396a214 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransport/README.md @@ -0,0 +1,307 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m new file mode 100644 index 00000000..9e3745f4 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m @@ -0,0 +1,95 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" + +#import + +@implementation GDTCCTCompressionHelper + ++ (nullable NSData *)gzippedData:(NSData *)data { +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (data.length > UINT_MAX) { + return nil; + } +#endif + + const uint kChunkSize = 1024; + + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if (deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, Z_DEFAULT_STRATEGY) != Z_OK) { + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + ++ (BOOL)isGzipped:(NSData *)data { + const UInt8 *bytes = (const UInt8 *)data.bytes; + return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m new file mode 100644 index 00000000..ba659136 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m @@ -0,0 +1,275 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#import +#import +#import +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +#pragma mark - General purpose encoders + +pb_bytes_array_t *GDTCCTEncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return GDTCCTEncodeData(stringBytes); +} + +pb_bytes_array_t *GDTCCTEncodeData(NSData *data) { + pb_bytes_array_t *pbBytesArray = calloc(1, PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + if (pbBytesArray != NULL) { + [data getBytes:pbBytesArray->bytes length:data.length]; + pbBytesArray->size = (pb_size_t)data.length; + } + return pbBytesArray; +} + +#pragma mark - CCT object constructors + +NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + CFDataSetLength(dataRef, bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + + return CFBridgingRelease(dataRef); +} + +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet) { + gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default; + NSUInteger numberOfLogRequests = logMappingIDToLogSet.count; + gdt_cct_LogRequest *logRequests = calloc(numberOfLogRequests, sizeof(gdt_cct_LogRequest)); + if (logRequests == NULL) { + return batchedLogRequest; + } + + __block int i = 0; + [logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull logMappingID, + NSSet *_Nonnull logSet, + BOOL *_Nonnull stop) { + int32_t logSource = [logMappingID intValue]; + gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet); + logRequests[i] = logRequest; + i++; + }]; + + batchedLogRequest.log_request = logRequests; + batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests; + return batchedLogRequest; +} + +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, + NSSet *_Nonnull logSet) { + if (logSet.count == 0) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"An empty event set can't be serialized to proto."); + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + return logRequest; + } + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + logRequest.log_source = logSource; + logRequest.has_log_source = 1; + logRequest.client_info = GDTCCTConstructClientInfo(); + logRequest.has_client_info = 1; + logRequest.log_event = calloc(logSet.count, sizeof(gdt_cct_LogEvent)); + if (logRequest.log_event == NULL) { + return logRequest; + } + int i = 0; + for (GDTCOREvent *log in logSet) { + gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log); + logRequest.log_event[i] = logEvent; + i++; + } + logRequest.log_event_count = (pb_size_t)logSet.count; + + GDTCORClock *currentTime = [GDTCORClock snapshot]; + logRequest.request_time_ms = currentTime.timeMillis; + logRequest.has_request_time_ms = 1; + logRequest.request_uptime_ms = currentTime.uptime; + logRequest.has_request_uptime_ms = 1; + + return logRequest; +} + +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event) { + gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default; + logEvent.event_time_ms = event.clockSnapshot.timeMillis; + logEvent.has_event_time_ms = 1; + logEvent.event_uptime_ms = event.clockSnapshot.uptime; + logEvent.has_event_uptime_ms = 1; + logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds; + logEvent.has_timezone_offset_seconds = 1; + if (event.customBytes) { + NSData *networkConnectionInfoData = event.networkConnectionInfoData; + if (networkConnectionInfoData) { + [networkConnectionInfoData getBytes:&logEvent.network_connection_info + length:networkConnectionInfoData.length]; + logEvent.has_network_connection_info = 1; + } + NSNumber *eventCode = event.eventCode; + if (eventCode != nil) { + logEvent.has_event_code = 1; + logEvent.event_code = [eventCode intValue]; + } + } + NSError *error; + NSData *extensionBytes; + if (event.fileURL) { + extensionBytes = [NSData dataWithContentsOfFile:event.fileURL.path options:0 error:&error]; + } else { + GDTCORLogError(GDTCORMCEFileReadError, @"%@", @"An event's fileURL property was nil."); + return logEvent; + } + if (error) { + GDTCORLogWarning(GDTCORMCWFileReadError, + @"There was an error reading extension bytes from disk: %@", error); + return logEvent; + } + logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file. + return logEvent; +} + +gdt_cct_ClientInfo GDTCCTConstructClientInfo() { + gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default; + clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE; + clientInfo.has_client_type = 1; +#if TARGET_OS_IOS || TARGET_OS_TV + clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo(); + clientInfo.has_ios_client_info = 1; +#elif TARGET_OS_OSX + // TODO(mikehaney24): Expand the proto to include macOS client info. +#endif + return clientInfo; +} + +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() { + gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default; +#if TARGET_OS_IOS || TARGET_OS_TV + UIDevice *device = [UIDevice currentDevice]; + NSBundle *bundle = [NSBundle mainBundle]; + NSLocale *locale = [NSLocale currentLocale]; + iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion); + NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."]; + iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]); + NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; + if (version) { + iOSClientInfo.application_build = GDTCCTEncodeString(version); + } + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + if (countryCode) { + iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]); + } + iOSClientInfo.model = GDTCCTEncodeString(device.model); + NSString *languageCode = bundle.preferredLocalizations.firstObject; + iOSClientInfo.language_code = + languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en"); + iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier); +#endif + return iOSClientInfo; +} + +NSData *GDTCCTConstructNetworkConnectionInfoData() { + gdt_cct_NetworkConnectionInfo networkConnectionInfo = gdt_cct_NetworkConnectionInfo_init_default; + NSInteger currentNetworkType = GDTCORNetworkTypeMessage(); + if (currentNetworkType) { + networkConnectionInfo.has_network_type = 1; + if (currentNetworkType == GDTCORNetworkTypeMobile) { + networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE; + networkConnectionInfo.mobile_subtype = GDTCCTNetworkConnectionInfoNetworkMobileSubtype(); + if (networkConnectionInfo.mobile_subtype != + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE) { + networkConnectionInfo.has_mobile_subtype = 1; + } + } else { + networkConnectionInfo.network_type = gdt_cct_NetworkConnectionInfo_NetworkType_WIFI; + } + } + NSData *networkConnectionInfoData = [NSData dataWithBytes:&networkConnectionInfo + length:sizeof(networkConnectionInfo)]; + return networkConnectionInfoData; +} + +gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype() { + NSNumber *networkMobileSubtypeMessage = @(GDTCORNetworkMobileSubTypeMessage()); + if (!networkMobileSubtypeMessage.intValue) { + return gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; + } + static NSDictionary *MessageToNetworkSubTypeMessage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + MessageToNetworkSubTypeMessage = @{ + @(GDTCORNetworkMobileSubtypeGPRS) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS), + @(GDTCORNetworkMobileSubtypeEdge) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE), + @(GDTCORNetworkMobileSubtypeWCDMA) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE), + @(GDTCORNetworkMobileSubtypeHSDPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA), + @(GDTCORNetworkMobileSubtypeHSUPA) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA), + @(GDTCORNetworkMobileSubtypeCDMA1x) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA), + @(GDTCORNetworkMobileSubtypeCDMAEVDORev0) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0), + @(GDTCORNetworkMobileSubtypeCDMAEVDORevA) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A), + @(GDTCORNetworkMobileSubtypeCDMAEVDORevB) : + @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B), + @(GDTCORNetworkMobileSubtypeHRPD) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD), + @(GDTCORNetworkMobileSubtypeLTE) : @(gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE), + }; + }); + NSNumber *networkMobileSubtype = MessageToNetworkSubTypeMessage[networkMobileSubtypeMessage]; + return networkMobileSubtype.intValue; +} + +#pragma mark - CCT Object decoders + +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) { + gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default; + pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]); + if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) { + NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)]; + NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error}; + if (error != NULL) { + *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo]; + } + response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default; + } + return response; +} diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m new file mode 100644 index 00000000..d0382cc2 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m @@ -0,0 +1,426 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import +#import +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +const static int64_t kMillisPerDay = 8.64e+7; + +/** Creates and/or returns a singleton NSString that is the NSCoding file location. + * + * @return The NSCoding file path. + */ +static NSString *ArchivePath() { + static NSString *archivePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + archivePath = [GDTCORRootDirectory() URLByAppendingPathComponent:@"GDTCCTPrioritizer"].path; + }); + return archivePath; +} + +/** This class extension is for declaring private properties. */ +@interface GDTCCTPrioritizer () + +/** All CCT events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CCTEvents; + +/** All FLL events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *FLLEvents; + +/** All CSH events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CSHEvents; + +@end + +@implementation GDTCCTPrioritizer + ++ (void)load { + GDTCCTPrioritizer *prioritizer = [GDTCCTPrioritizer sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCSH]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + ++ (instancetype)sharedInstance { + static GDTCCTPrioritizer *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTPrioritizer alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _queue = dispatch_queue_create("com.google.GDTCCTPrioritizer", DISPATCH_QUEUE_SERIAL); + _CCTEvents = [[NSMutableSet alloc] init]; + _FLLEvents = [[NSMutableSet alloc] init]; + _CSHEvents = [[NSMutableSet alloc] init]; + } + return self; +} + +- (nullable NSSet *)eventsForTarget:(GDTCORTarget)target { + __block NSSet *events; + dispatch_sync(_queue, ^{ + switch (target) { + case kGDTCORTargetCCT: + events = [self->_CCTEvents copy]; + break; + + case kGDTCORTargetFLL: + events = [self->_FLLEvents copy]; + break; + + case kGDTCORTargetCSH: + events = [self->_CSHEvents copy]; + break; + + default: + break; + } + }); + return events; +} + +#pragma mark - GDTCORPrioritizer Protocol + +- (void)prioritizeEvent:(GDTCOREvent *)event { + if (event.needsNetworkConnectionInfoPopulated) { + event.networkConnectionInfoData = GDTCCTConstructNetworkConnectionInfoData(); + } + dispatch_async(_queue, ^{ + switch (event.target) { + case kGDTCORTargetCCT: + [self.CCTEvents addObject:event]; + break; + + case kGDTCORTargetFLL: + [self.FLLEvents addObject:event]; + break; + + case kGDTCORTargetCSH: + [self.CSHEvents addObject:event]; + break; + + default: + GDTCORLogDebug(@"GDTCCTPrioritizer doesn't support target %ld", (long)event.target); + break; + } + }); +} + +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORUploadPackage *package = [[GDTCORUploadPackage alloc] initWithTarget:target]; + dispatch_sync(_queue, ^{ + NSSet *eventsThatWillBeSent = [self eventsForTarget:target + conditions:conditions]; + package.events = eventsThatWillBeSent; + }); + GDTCORLogDebug(@"CCT: %lu events are in the upload package", (unsigned long)package.events.count); + return package; +} + +#pragma mark - Private helper methods + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCCTQoSTier) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCCTQoSDefault = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCCTQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCCTQoSDaily = 2, + + /** This event should only be uploaded on wifi. */ + GDTCCTQoSWifiOnly = 5, +}; + +- (void)saveState { + dispatch_sync(_queue, ^{ + NSError *error; + GDTCOREncodeArchive(self, ArchivePath(), &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCCTPrioritizer to an archive failed: %@", error); + } + }); + GDTCORLogDebug(@"GDTCCTPrioritizer saved state to %@ as requested by GDT.", ArchivePath()); +} + +/** Converts a GDTCOREventQoS to a GDTCCTQoS tier. + * + * @param qosTier The GDTCOREventQoS value. + * @return A static NSNumber that represents the CCT QoS tier. + */ +FOUNDATION_STATIC_INLINE +NSNumber *GDTCCTQosTierFromGDTCOREventQosTier(GDTCOREventQoS qosTier) { + switch (qosTier) { + case GDTCOREventQoSWifiOnly: + return @(GDTCCTQoSWifiOnly); + break; + + case GDTCOREventQoSTelemetry: + // falls through. + case GDTCOREventQoSDaily: + return @(GDTCCTQoSDaily); + break; + + default: + return @(GDTCCTQoSDefault); + break; + } +} + +/** Constructs a set of events for upload to CCT, FLL, or CSH backends. These backends are + * request-proto and batching compatible, so they construct event batches the same way. + * + * @param conditions The set of conditions the upload package should be made under. + * @param target The target backend. + * @return A set of events for the target. + */ +- (NSSet *)eventsForTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORClock __strong **timeOfLastDailyUpload = NULL; + NSSet *eventsToFilter; + switch (target) { + case kGDTCORTargetCCT: + eventsToFilter = self.CCTEvents; + timeOfLastDailyUpload = &self->_CCTTimeOfLastDailyUpload; + break; + + case kGDTCORTargetFLL: + eventsToFilter = self.FLLEvents; + timeOfLastDailyUpload = &self->_FLLOfLastDailyUpload; + break; + + case kGDTCORTargetCSH: + // This backend doesn't batch and uploads all events as soon as possible without respect to + // any upload condition. + return self.CSHEvents; + break; + + default: + // Return an empty set. + return [[NSSet alloc] init]; + break; + } + + NSMutableSet *eventsThatWillBeSent = [[NSMutableSet alloc] init]; + // A high priority event effectively flushes all events to be sent. + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + GDTCORLogDebug(@"%@", @"CCT: A high priority event is flushing all events."); + return eventsToFilter; + } + + // If on wifi, upload logs that are ok to send on wifi. + if ((conditions & GDTCORUploadConditionWifiData) == GDTCORUploadConditionWifiData) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnWifi:eventsToFilter]]; + GDTCORLogDebug(@"%@", @"CCT: events ok to send on wifi are being added to the upload package"); + } else { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnMobileData:eventsToFilter]]; + GDTCORLogDebug(@"%@", + @"CCT: events ok to send on mobile are being added to the upload package"); + } + + // If it's been > 24h since the last daily upload, upload logs with the daily QoS. + if (*timeOfLastDailyUpload) { + int64_t millisSinceLastUpload = + [GDTCORClock snapshot].timeMillis - (*timeOfLastDailyUpload).timeMillis; + if (millisSinceLastUpload > kMillisPerDay) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug(@"%@", @"CCT: events ok to send daily are being added to the upload package"); + } + } else { + *timeOfLastDailyUpload = [GDTCORClock snapshot]; + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug(@"%@", @"CCT: events ok to send daily are being added to the upload package"); + } + return eventsThatWillBeSent; +} + +/** Returns a set of logs that are ok to upload whilst on mobile data. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on mobile data. + */ +- (NSSet *)logEventsOkToSendOnMobileData:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDefault)]; + }]; +} + +/** Returns a set of logs that are ok to upload whilst on wifi. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on wifi. + */ +- (NSSet *)logEventsOkToSendOnWifi:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) { + NSNumber *qosTier = GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier); + return [qosTier isEqual:@(GDTCCTQoSDefault)] || [qosTier isEqual:@(GDTCCTQoSWifiOnly)] || + [qosTier isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +/** Returns a set of logs that only should have a single upload attempt per day. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload only once per day. + */ +- (NSSet *)logEventsOkToSendDaily:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +#pragma mark - NSSecureCoding + +/** NSSecureCoding key for the CCTEvents property. */ +static NSString *const GDTCCTUploaderCCTEventsKey = @"GDTCCTUploaderCCTEventsKey"; + +/** NSSecureCoding key for the CCTEvents property. */ +static NSString *const GDTCCTUploaderFLLEventsKey = @"GDTCCTUploaderFLLEventsKey"; + +/** NSSecureCoding key for the CCTEvents property. */ +static NSString *const GDTCCTUploaderCSHEventsKey = @"GDTCCTUploaderCSHEventsKey"; + +- (instancetype)initWithCoder:(NSCoder *)coder { + GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance]; + if (sharedInstance) { + NSSet *classes = [NSSet setWithObjects:[NSMutableSet class], [GDTCOREvent class], nil]; + NSMutableSet *decodedCCTEvents = [coder decodeObjectOfClasses:classes + forKey:GDTCCTUploaderCCTEventsKey]; + if (decodedCCTEvents) { + sharedInstance->_CCTEvents = decodedCCTEvents; + } + NSMutableSet *decodedFLLEvents = [coder decodeObjectOfClasses:classes + forKey:GDTCCTUploaderFLLEventsKey]; + if (decodedFLLEvents) { + sharedInstance->_FLLEvents = decodedFLLEvents; + } + NSMutableSet *decodedCSHEvents = [coder decodeObjectOfClasses:classes + forKey:GDTCCTUploaderCSHEventsKey]; + if (decodedCSHEvents) { + sharedInstance->_CSHEvents = decodedCSHEvents; + } + } + return sharedInstance; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + GDTCCTPrioritizer *sharedInstance = [GDTCCTPrioritizer sharedInstance]; + if (!sharedInstance) { + return; + } + NSMutableSet *CCTEvents = sharedInstance->_CCTEvents; + if (CCTEvents) { + [coder encodeObject:CCTEvents forKey:GDTCCTUploaderCCTEventsKey]; + } + NSMutableSet *FLLEvents = sharedInstance->_FLLEvents; + if (FLLEvents) { + [coder encodeObject:FLLEvents forKey:GDTCCTUploaderFLLEventsKey]; + } + NSMutableSet *CSHEvents = sharedInstance->_CSHEvents; + if (CSHEvents) { + [coder encodeObject:CSHEvents forKey:GDTCCTUploaderCSHEventsKey]; + } +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + dispatch_async(_queue, ^{ + NSError *error; + GDTCORDecodeArchive([GDTCCTPrioritizer class], ArchivePath(), nil, &error); + if (error) { + GDTCORLogDebug(@"Deserializing GDTCCTPrioritizer from an archive failed: %@", error); + } + }); +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_queue, ^{ + // Immediately request a background task to run until the end of the current queue of work, and + // cancel it once the work is done. + __block GDTCORBackgroundIdentifier bgID = + [app beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + NSError *error; + GDTCOREncodeArchive(self, ArchivePath(), &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCCTPrioritizer to an archive failed: %@", error); + } + + // End the background task if it's still valid. + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_queue, ^{ + NSError *error; + GDTCOREncodeArchive(self, ArchivePath(), &error); + if (error) { + GDTCORLogDebug(@"Serializing GDTCCTPrioritizer to an archive failed: %@", error); + } + }); +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + // If sending the package wasn't successful, we should keep track of these events. + if (!successful) { + return; + } + + dispatch_async(_queue, ^{ + NSSet *events = [package.events copy]; + for (GDTCOREvent *event in events) { + // We don't know what collection the event was contained in, so attempt removal from all. + [self.CCTEvents removeObject:event]; + [self.FLLEvents removeObject:event]; + [self.CSHEvents removeObject:event]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + [self packageDelivered:package successful:YES]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m new file mode 100644 index 00000000..f50c9bf5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m @@ -0,0 +1,441 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTUploader.h" + +#import +#import +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +#ifdef GDTCCTSUPPORT_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static NSString *const kGDTCCTSupportSDKVersion = @STR(GDTCCTSUPPORT_VERSION); +#else +static NSString *const kGDTCCTSupportSDKVersion = @"UNKNOWN"; +#endif // GDTCCTSUPPORT_VERSION + +#if !NDEBUG +NSNotificationName const GDTCCTUploadCompleteNotification = @"com.GDTCCTUploader.UploadComplete"; +#endif // #if !NDEBUG + +@interface GDTCCTUploader () + +// Redeclared as readwrite. +@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask; + +@end + +@implementation GDTCCTUploader + ++ (void)load { + GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTUploader *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTUploader alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL); + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + _uploaderSession = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + } + return self; +} + +/** + * + */ +- (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target { + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + static NSURL *CCTServerURL; + static dispatch_once_t CCTOnceToken; + dispatch_once(&CCTOnceToken, ^{ + const char *p1 = "hts/frbslgiggolai.o/0clgbth"; + const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac"; + const char URL[54] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'}; + CCTServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *FLLServerURL; + static dispatch_once_t FLLOnceToken; + dispatch_once(&FLLOnceToken, ^{ + const char *p1 = "hts/frbslgigp.ogepscmv/ieo/eaybtho"; + const char *p2 = "tp:/ieaeogn-agolai.o/1frlglgc/aclg"; + const char URL[69] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], '\0'}; + FLLServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *CSHServerURL; + static dispatch_once_t CSHOnceToken; + dispatch_once(&CSHOnceToken, ^{ + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + const char *p1 = "hts/cahyiseot-agolai.o/1frlglgc/aclg"; + const char *p2 = "tp:/rsltcrprsp.ogepscmv/ieo/eaybtho"; + const char URL[72] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], p1[34], p2[34], p1[35], '\0'}; + CSHServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + +#if !NDEBUG + if (_testServerURL) { + return _testServerURL; + } +#endif // !NDEBUG + + switch (target) { + case kGDTCORTargetCCT: + return CCTServerURL; + + case kGDTCORTargetFLL: + return FLLServerURL; + + case kGDTCORTargetCSH: + return CSHServerURL; + + default: + GDTCORLogDebug(@"GDTCCTUploader doesn't support target %ld", (long)target); + return nil; + break; + } +} + +- (NSString *)FLLAndCSHAPIKey { + static NSString *defaultServerKey; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // These strings should be interleaved to construct the real key. + const char *p1 = "AzSBG0honD6A-PxV5nBc"; + const char *p2 = "Iay44Iwtu2vV0AOrz1C"; + const char defaultKey[40] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], + p1[4], p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], + p1[8], p2[8], p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], + p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], + p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'}; + defaultServerKey = [NSString stringWithUTF8String:defaultKey]; + }); + return defaultServerKey; +} + +- (void)uploadPackage:(GDTCORUploadPackage *)package { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTCCTUploader-upload" + expirationHandler:^{ + if (bgID != GDTCORBackgroundIdentifierInvalid) { + // Cancel the upload and complete delivery. + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + + // End the background task. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + } + }]; + + dispatch_async(_uploaderQueue, ^{ + if (self->_currentTask || self->_currentUploadPackage) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"%@", + @"An upload shouldn't be initiated with another in progress."); + return; + } + GDTCORTarget target = package.target; + id completionHandler = ^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + GDTCORLogDebug(@"%@", @"CCT: request completed"); + if (error) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"There was an error uploading events: %@", error); + } + NSError *decodingError; + GDTCORClock *futureUploadTime; + if (data) { + gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError); + if (!decodingError && logResponse.has_next_request_wait_millis) { + GDTCORLogDebug( + @"CCT: The backend responded asking to not upload for %lld millis from now.", + logResponse.next_request_wait_millis); + futureUploadTime = + [GDTCORClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis]; + } else if (decodingError) { + GDTCORLogDebug(@"There was a response decoding error: %@", decodingError); + } + pb_release(gdt_cct_LogResponse_fields, &logResponse); + } + if (!futureUploadTime) { + GDTCORLogDebug(@"%@", @"CCT: The backend response failed to parse, so the next request " + @"won't occur until 15 minutes from now"); + // 15 minutes from now. + futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:15 * 60 * 1000]; + } + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + default: + break; + } + + // Only retry if one of these codes is returned, or there was an error. + if (error || ((NSHTTPURLResponse *)response).statusCode == 429 || + ((NSHTTPURLResponse *)response).statusCode == 503) { + [package retryDeliveryInTheFuture]; + } else { +#if !NDEBUG + // Post a notification when in DEBUG mode to state how many packages were uploaded. Useful + // for validation during tests. + [[NSNotificationCenter defaultCenter] postNotificationName:GDTCCTUploadCompleteNotification + object:@(package.events.count)]; +#endif // #if !NDEBUG + GDTCORLogDebug(@"%@", @"CCT: package delivered"); + [package completeDelivery]; + } + + // End the background task if there was one. + if (bgID != GDTCORBackgroundIdentifierInvalid) { + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + } + self.currentTask = nil; + self.currentUploadPackage = nil; + }; + self->_currentUploadPackage = package; + NSData *requestProtoData = + [self constructRequestProtoFromPackage:(GDTCORUploadPackage *)package]; + NSData *gzippedData = [GDTCCTCompressionHelper gzippedData:requestProtoData]; + BOOL usingGzipData = gzippedData != nil && gzippedData.length < requestProtoData.length; + NSData *dataToSend = usingGzipData ? gzippedData : requestProtoData; + NSURLRequest *request = [self constructRequestForTarget:target data:dataToSend]; + GDTCORLogDebug(@"CTT: request created: %@", request); + self.currentTask = [self.uploaderSession uploadTaskWithRequest:request + fromData:dataToSend + completionHandler:completionHandler]; + GDTCORLogDebug(@"%@", @"CCT: The upload task is about to begin."); + [self.currentTask resume]; + }); +} + +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions { + __block BOOL result = NO; + NSSet *CSHEvents = [[GDTCCTPrioritizer sharedInstance] eventsForTarget:kGDTCORTargetCSH]; + dispatch_sync(_uploaderQueue, ^{ + if (target == kGDTCORTargetCSH) { + result = CSHEvents.count > 0; + return; + } + + if (self->_currentUploadPackage) { + result = NO; + GDTCORLogDebug(@"%@", @"CCT: can't upload because a package is in flight"); + return; + } + if (self->_currentTask) { + result = NO; + GDTCORLogDebug(@"%@", @"CCT: can't upload because a task is in progress"); + return; + } + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + result = YES; + GDTCORLogDebug(@"%@", @"CCT: a high priority event is allowing an upload"); + return; + } + switch (target) { + case kGDTCORTargetCCT: + if (self->_CCTNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_CCTNextUploadTime]; + } + break; + + case kGDTCORTargetFLL: + if (self->_FLLNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_FLLNextUploadTime]; + } + break; + + default: + // The CSH backend should be handled above. + break; + } + if (result) { + GDTCORLogDebug(@"CCT: can upload to target %ld because the request wait time has transpired", + (long)target); + } else { + GDTCORLogDebug(@"CCT: can't upload to target %ld because the backend asked to wait", + (long)target); + } + result = YES; + GDTCORLogDebug(@"CCT: can upload to target %ld because nothing is preventing it", (long)target); + }); + return result; +} + +#pragma mark - Private helper methods + +/** Constructs data given an upload package. + * + * @param package The upload package used to construct the request proto bytes. + * @return Proto bytes representing a gdt_cct_LogRequest object. + */ +- (nonnull NSData *)constructRequestProtoFromPackage:(GDTCORUploadPackage *)package { + // Segment the log events by log type. + NSMutableDictionary *> *logMappingIDToLogSet = + [[NSMutableDictionary alloc] init]; + [package.events enumerateObjectsUsingBlock:^(GDTCOREvent *_Nonnull event, BOOL *_Nonnull stop) { + NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID]; + logSet = logSet ? logSet : [[NSMutableSet alloc] init]; + [logSet addObject:event]; + logMappingIDToLogSet[event.mappingID] = logSet; + }]; + + gdt_cct_BatchedLogRequest batchedLogRequest = + GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet); + + NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest); + pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest); + return data ? data : [[NSData alloc] init]; +} + +/** Constructs a request to FLL given a URL and request body data. + * + * @param target The target backend to send the request to. + * @param data The request body data. + * @return A new NSURLRequest ready to be sent to FLL. + */ +- (NSURLRequest *)constructRequestForTarget:(GDTCORTarget)target data:(NSData *)data { + NSURL *URL = [self serverURLForTarget:target]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + NSString *targetString; + switch (target) { + case kGDTCORTargetCCT: + targetString = @"cct"; + break; + + case kGDTCORTargetFLL: + targetString = @"fll"; + break; + + case kGDTCORTargetCSH: + targetString = @"csh"; + break; + + default: + targetString = @"unknown"; + break; + } + NSString *userAgent = + [NSString stringWithFormat:@"datatransport/%@ %@support/%@ apple/", kGDTCORVersion, + targetString, kGDTCCTSupportSDKVersion]; + if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) { + [request setValue:[self FLLAndCSHAPIKey] forHTTPHeaderField:@"X-Goog-Api-Key"]; + } + if ([GDTCCTCompressionHelper isGzipped:data]) { + [request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + } + [request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + request.HTTPMethod = @"POST"; + [request setHTTPBody:data]; + return request; +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageExpired:(GDTCORUploadPackage *)package { + dispatch_async(_uploaderQueue, ^{ + [self.currentTask cancel]; + self.currentTask = nil; + self.currentUploadPackage = nil; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_uploaderQueue, ^{ + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + }); +} + +#pragma mark - NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { + if (!completionHandler) { + return; + } + if (response.statusCode == 302 || response.statusCode == 301) { + if ([request.URL isEqual:[self serverURLForTarget:kGDTCORTargetFLL]]) { + NSURLRequest *newRequest = [self constructRequestForTarget:kGDTCORTargetCCT + data:task.originalRequest.HTTPBody]; + completionHandler(newRequest); + } + } else { + completionHandler(request); + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m new file mode 100644 index 00000000..1531e565 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m @@ -0,0 +1,236 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h" + +#import + +NSString *const GDTCCTNeedsNetworkConnectionInfo = @"needs_network_connection_info"; + +NSString *const GDTCCTNetworkConnectionInfo = @"network_connection_info"; + +NSString *const GDTCCTEventCodeInfo = @"event_code_info"; + +@implementation GDTCOREvent (GDTCCTSupport) + +- (void)setNeedsNetworkConnectionInfoPopulated:(BOOL)needsNetworkConnectionInfoPopulated { + if (!needsNetworkConnectionInfoPopulated) { + if (!self.customBytes) { + return; + } + + // Make sure we don't destroy the eventCode data, if any is present. + @try { + NSError *error; + NSMutableDictionary *bytesDict = + [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + NSNumber *eventCode = bytesDict[GDTCCTEventCodeInfo]; + if (eventCode != nil) { + self.customBytes = + [NSJSONSerialization dataWithJSONObject:@{GDTCCTEventCodeInfo : eventCode} + options:0 + error:&error]; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } else { + @try { + NSError *error; + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:@YES forKey:GDTCCTNeedsNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting the event for needs_network_connection_info: %@", + exception); + } + } +} + +- (BOOL)needsNetworkConnectionInfoPopulated { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + return bytesDict && !error && [bytesDict[GDTCCTNeedsNetworkConnectionInfo] boolValue]; + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when checking the event for needs_network_connection_info: %@", + exception); + } + } + return NO; +} + +- (void)setNetworkConnectionInfoData:(NSData *)networkConnectionInfoData { + @try { + NSError *error; + NSString *dataString = [networkConnectionInfoData base64EncodedStringWithOptions:0]; + if (dataString != nil) { + NSMutableDictionary *bytesDict; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an even'ts event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + [bytesDict setObject:dataString forKey:GDTCCTNetworkConnectionInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + } + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", exception); + } +} + +- (nullable NSData *)networkConnectionInfoData { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *base64Data = bytesDict[GDTCCTNetworkConnectionInfo]; + NSData *networkConnectionInfoData = [[NSData alloc] initWithBase64EncodedString:base64Data + options:0]; + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return networkConnectionInfoData; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } + } + return nil; +} + +- (NSNumber *)eventCode { + if (self.customBytes) { + @try { + NSError *error; + NSDictionary *bytesDict = [NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error]; + NSString *eventCodeString = bytesDict[GDTCCTEventCodeInfo]; + + if (!eventCodeString) { + return nil; + } + + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + NSNumber *eventCode = [formatter numberFromString:eventCodeString]; + + if (error) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", error); + return nil; + } else { + return eventCode; + } + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's event_code: %@", exception); + } + } + return nil; +} + +- (void)setEventCode:(NSNumber *)eventCode { + if (eventCode == nil) { + if (!self.customBytes) { + return; + } + + NSError *error; + NSMutableDictionary *bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes + options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + + [bytesDict removeObjectForKey:GDTCCTEventCodeInfo]; + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + return; + } + + @try { + NSMutableDictionary *bytesDict; + NSError *error; + if (self.customBytes) { + bytesDict = [[NSJSONSerialization JSONObjectWithData:self.customBytes options:0 + error:&error] mutableCopy]; + if (error) { + GDTCORLogDebug(@"Error when setting an event's event_code: %@", error); + return; + } + } else { + bytesDict = [[NSMutableDictionary alloc] init]; + } + + NSString *eventCodeString = [eventCode stringValue]; + if (eventCodeString == nil) { + return; + } + + [bytesDict setObject:eventCodeString forKey:GDTCCTEventCodeInfo]; + + self.customBytes = [NSJSONSerialization dataWithJSONObject:bytesDict options:0 error:&error]; + if (error) { + self.customBytes = nil; + GDTCORLogDebug(@"Error when setting an event's network_connection_info: %@", error); + return; + } + + } @catch (NSException *exception) { + GDTCORLogDebug(@"Error when getting an event's network_connection_info: %@", exception); + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h new file mode 100644 index 00000000..08d0a4ba --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A class with methods to help with gzipped data. */ +@interface GDTCCTCompressionHelper : NSObject + +/** Compresses the given data and returns a new data object. + * + * @note Reduced version from GULNSData+zlib.m of GoogleUtilities. + * @return Compressed data, or nil if there was an error. + */ ++ (nullable NSData *)gzippedData:(NSData *)data; + +/** Returns YES if the data looks like it was gzip compressed by checking for the gzip magic number. + * + * @note: From https://en.wikipedia.org/wiki/Gzip, gzip's magic number is 1f 8b. + * @return YES if the data appears gzipped, NO otherwise. + */ ++ (BOOL)isGzipped:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h new file mode 100644 index 00000000..8051f0e2 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h @@ -0,0 +1,128 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - General purpose encoders + +/** Converts an NSString* to a pb_bytes_array_t*. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param string The string to convert. + * @return A newly allocated array of bytes representing the UTF8 encoding of the string. + */ +pb_bytes_array_t *GDTCCTEncodeString(NSString *string); + +/** Converts an NSData to a pb_bytes_array_t*. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param data The data to convert. + * @return A newly allocated array of bytes with [data bytes] copied into it. + */ +pb_bytes_array_t *GDTCCTEncodeData(NSData *data); + +#pragma mark - CCT object constructors + +/** Encodes a batched log request. + * + * @note Ensure that pb_release is called on the batchedLogRequest param. + * + * @param batchedLogRequest A pointer to the log batch to encode to bytes. + * @return An NSData object representing the bytes of the log request batch. + */ +FOUNDATION_EXPORT +NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest); + +/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch. + * @return A newly created gdt_cct_BatchedLogRequest. + */ +FOUNDATION_EXPORT +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet); + +/** Constructs a log request given a log source and a set of events. + * + * @note calloc is called in this method. Ensure that pb_release is called on this or the parent. + * @param logSource The CCT log source to put into the log request. + * @param logSet The set of events to send in this log request. + */ +FOUNDATION_EXPORT +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet *logSet); + +/** Constructs a gdt_cct_LogEvent given a GDTCOREvent*. + * + * @param event The GDTCOREvent to convert. + * @return The new gdt_cct_LogEvent object. + */ +FOUNDATION_EXPORT +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCOREvent *event); + +/** Constructs a gdt_cct_ClientInfo representing the client device. + * + * @return The new gdt_cct_ClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_ClientInfo GDTCCTConstructClientInfo(void); + +/** Constructs a gdt_cct_IosClientInfo representing the client device. + * + * @return The new gdt_cct_IosClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void); + +/** Constructs the data of a gdt_cct_NetworkConnectionInfo representing the client nework connection + * information. + * + * @return The data of a gdt_cct_NetworkConnectionInfo object. + */ +FOUNDATION_EXPORT +NSData *GDTCCTConstructNetworkConnectionInfoData(void); + +/** Return a gdt_cct_NetworkConnectionInfo_MobileSubtype representing the client + * + * @return The gdt_cct_NetworkConnectionInfo_MobileSubtype. + */ +FOUNDATION_EXPORT +gdt_cct_NetworkConnectionInfo_MobileSubtype GDTCCTNetworkConnectionInfoNetworkMobileSubtype(void); + +#pragma mark - CCT object decoders + +/** Decodes a gdt_cct_LogResponse given proto bytes. + * + * @note calloc is called in this method. Ensure that pb_release is called on the return value. + * + * @param data The proto bytes of the gdt_cct_LogResponse. + * @param error An error that will be populated if something went wrong during decoding. + * @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly. + */ +FOUNDATION_EXPORT +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error); + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h new file mode 100644 index 00000000..7b7921b3 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the prioritization of events from GoogleDataTransport. */ +@interface GDTCCTPrioritizer : NSObject + +/** The queue on which this prioritizer operates. */ +@property(nonatomic) dispatch_queue_t queue; + +/** The most recent attempted upload of CCT daily uploaded logs. */ +@property(nonatomic) GDTCORClock *CCTTimeOfLastDailyUpload; + +/** The most recent attempted upload of FLL daily uploaded logs*/ +@property(nonatomic) GDTCORClock *FLLOfLastDailyUpload; + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** Returns a set of events that have been prioritized for the given target. + * + * @param target The target to check. CCT, FLL, and CSH are currently supported by this class. + * @return The set of events prioritized so far. + */ +- (nullable NSSet *)eventsForTarget:(GDTCORTarget)target; + +NS_ASSUME_NONNULL_END + +@end diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h new file mode 100644 index 00000000..cdc322d4 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +#if !NDEBUG +/** A notification fired when uploading is complete, detailing the number of events uploaded. */ +extern NSNotificationName const GDTCCTUploadCompleteNotification; +#endif // #if !NDEBUG + +/** Class capable of uploading events to the CCT backend. */ +@interface GDTCCTUploader : NSObject + +/** The queue on which all CCT uploading will occur. */ +@property(nonatomic, readonly) dispatch_queue_t uploaderQueue; + +/** The URL session that will attempt upload. */ +@property(nonatomic, readonly) NSURLSession *uploaderSession; + +/** The current upload task. */ +@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask; + +/** Current upload package. */ +@property(nullable, nonatomic) GDTCORUploadPackage *currentUploadPackage; + +/** The next upload time for the CCT target. */ +@property(nullable, nonatomic) GDTCORClock *CCTNextUploadTime; + +/** The next upload time for the FLL target. */ +@property(nullable, nonatomic) GDTCORClock *FLLNextUploadTime; + +#if !NDEBUG +/** An upload URL used across all targets. For testing only. */ +@property(nullable, nonatomic) NSURL *testServerURL; + +#endif // !NDEBUG + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c new file mode 100644 index 00000000..836031af --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c @@ -0,0 +1,128 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.5 */ + +#include "cct.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE; +const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; +const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT; +const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0; + + +const pb_field_t gdt_cct_LogEvent_fields[7] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0), + PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0), + PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0), + PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0), + PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = { + PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default), + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_IosClientInfo_fields[8] = { + PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0), + PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0), + PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0), + PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0), + PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0), + PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_ClientInfo_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogRequest_fields[7] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0), + PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields), + PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0), + PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0), + PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = { + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0), + PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTiersOverride_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogResponse_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields), + PB_LAST_FIELD +}; + + + + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h new file mode 100644 index 00000000..e9d9a12c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h @@ -0,0 +1,281 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.5 */ + +#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType { + gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5, + gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6, + gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7, + gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8, + gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15, + gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16, + gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17 +} gdt_cct_NetworkConnectionInfo_NetworkType; +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN +#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1)) + +typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype { + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2, + gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3, + gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6, + gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16, + gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19, + gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100 +} gdt_cct_NetworkConnectionInfo_MobileSubtype; +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1)) + +typedef enum _gdt_cct_ClientInfo_ClientType { + gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0, + gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15 +} gdt_cct_ClientInfo_ClientType; +#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN +#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE +#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1)) + +typedef enum _gdt_cct_QosTierConfiguration_QosTier { + gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2, + gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3, + gdt_cct_QosTierConfiguration_QosTier_NEVER = 4 +} gdt_cct_QosTierConfiguration_QosTier; +#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT +#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER +#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1)) + +/* Struct definitions */ +typedef struct _gdt_cct_BatchedLogRequest { + pb_size_t log_request_count; + struct _gdt_cct_LogRequest *log_request; +/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */ +} gdt_cct_BatchedLogRequest; + +typedef struct _gdt_cct_IosClientInfo { + pb_bytes_array_t *os_major_version; + pb_bytes_array_t *os_full_version; + pb_bytes_array_t *application_build; + pb_bytes_array_t *country; + pb_bytes_array_t *model; + pb_bytes_array_t *language_code; + pb_bytes_array_t *application_bundle_id; +/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */ +} gdt_cct_IosClientInfo; + +typedef struct _gdt_cct_ClientInfo { + bool has_client_type; + gdt_cct_ClientInfo_ClientType client_type; + bool has_ios_client_info; + gdt_cct_IosClientInfo ios_client_info; +/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */ +} gdt_cct_ClientInfo; + +typedef struct _gdt_cct_NetworkConnectionInfo { + bool has_network_type; + gdt_cct_NetworkConnectionInfo_NetworkType network_type; + bool has_mobile_subtype; + gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype; +/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */ +} gdt_cct_NetworkConnectionInfo; + +typedef struct _gdt_cct_QosTierConfiguration { + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; + bool has_log_source; + int32_t log_source; +/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */ +} gdt_cct_QosTierConfiguration; + +typedef struct _gdt_cct_QosTiersOverride { + pb_size_t qos_tier_configuration_count; + struct _gdt_cct_QosTierConfiguration *qos_tier_configuration; + bool has_qos_tier_fingerprint; + int64_t qos_tier_fingerprint; +/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */ +} gdt_cct_QosTiersOverride; + +typedef struct _gdt_cct_LogEvent { + bool has_event_time_ms; + int64_t event_time_ms; + pb_bytes_array_t *source_extension; + bool has_event_code; + int32_t event_code; + bool has_timezone_offset_seconds; + int64_t timezone_offset_seconds; + bool has_event_uptime_ms; + int64_t event_uptime_ms; + bool has_network_connection_info; + gdt_cct_NetworkConnectionInfo network_connection_info; +/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */ +} gdt_cct_LogEvent; + +typedef struct _gdt_cct_LogRequest { + bool has_client_info; + gdt_cct_ClientInfo client_info; + bool has_log_source; + int32_t log_source; + pb_size_t log_event_count; + struct _gdt_cct_LogEvent *log_event; + bool has_request_time_ms; + int64_t request_time_ms; + bool has_request_uptime_ms; + int64_t request_uptime_ms; + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */ +} gdt_cct_LogRequest; + +typedef struct _gdt_cct_LogResponse { + bool has_next_request_wait_millis; + int64_t next_request_wait_millis; + bool has_qos_tier; + gdt_cct_QosTiersOverride qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */ +} gdt_cct_LogResponse; + +/* Default values for struct fields */ +extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default; +extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default; +extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default; +extern const int32_t gdt_cct_QosTierConfiguration_log_source_default; + +/* Initializer values for message structs */ +#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default} +#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE} +#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default} +#define gdt_cct_BatchedLogRequest_init_default {0, NULL} +#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT} +#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default} +#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero} +#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN} +#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero} +#define gdt_cct_BatchedLogRequest_init_zero {0, NULL} +#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN} +#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define gdt_cct_BatchedLogRequest_log_request_tag 1 +#define gdt_cct_IosClientInfo_os_major_version_tag 3 +#define gdt_cct_IosClientInfo_os_full_version_tag 4 +#define gdt_cct_IosClientInfo_application_build_tag 5 +#define gdt_cct_IosClientInfo_country_tag 6 +#define gdt_cct_IosClientInfo_model_tag 7 +#define gdt_cct_IosClientInfo_language_code_tag 8 +#define gdt_cct_IosClientInfo_application_bundle_id_tag 11 +#define gdt_cct_ClientInfo_client_type_tag 1 +#define gdt_cct_ClientInfo_ios_client_info_tag 4 +#define gdt_cct_NetworkConnectionInfo_network_type_tag 1 +#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2 +#define gdt_cct_QosTierConfiguration_qos_tier_tag 2 +#define gdt_cct_QosTierConfiguration_log_source_tag 3 +#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1 +#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2 +#define gdt_cct_LogEvent_event_time_ms_tag 1 +#define gdt_cct_LogEvent_event_code_tag 11 +#define gdt_cct_LogEvent_event_uptime_ms_tag 17 +#define gdt_cct_LogEvent_source_extension_tag 6 +#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15 +#define gdt_cct_LogEvent_network_connection_info_tag 23 +#define gdt_cct_LogRequest_request_time_ms_tag 4 +#define gdt_cct_LogRequest_request_uptime_ms_tag 8 +#define gdt_cct_LogRequest_client_info_tag 1 +#define gdt_cct_LogRequest_log_source_tag 2 +#define gdt_cct_LogRequest_log_event_tag 3 +#define gdt_cct_LogRequest_qos_tier_tag 9 +#define gdt_cct_LogResponse_next_request_wait_millis_tag 1 +#define gdt_cct_LogResponse_qos_tier_tag 3 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t gdt_cct_LogEvent_fields[7]; +extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3]; +extern const pb_field_t gdt_cct_IosClientInfo_fields[8]; +extern const pb_field_t gdt_cct_ClientInfo_fields[3]; +extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2]; +extern const pb_field_t gdt_cct_LogRequest_fields[7]; +extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3]; +extern const pb_field_t gdt_cct_QosTiersOverride_fields[3]; +extern const pb_field_t gdt_cct_LogResponse_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* gdt_cct_LogEvent_size depends on runtime parameters */ +#define gdt_cct_NetworkConnectionInfo_size 13 +/* gdt_cct_IosClientInfo_size depends on runtime parameters */ +/* gdt_cct_ClientInfo_size depends on runtime parameters */ +/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */ +/* gdt_cct_LogRequest_size depends on runtime parameters */ +#define gdt_cct_QosTierConfiguration_size 13 +/* gdt_cct_QosTiersOverride_size depends on runtime parameters */ +/* gdt_cct_LogResponse_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CCT_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h new file mode 100644 index 00000000..e3a0b0ce --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A string sets in customBytes as a key paired to @YES if current event needs to + * populate network connection info data, @NO otherwise. + */ +FOUNDATION_EXPORT NSString *const GDTCCTNeedsNetworkConnectionInfo; + +/** A string sets in customBytes as a key paired to the network connection info data + * of current event. + */ +FOUNDATION_EXPORT NSString *const GDTCCTNetworkConnectionInfo; + +/** A category that uses the customBytes property of a GDTCOREvent to store network connection info. + */ +@interface GDTCOREvent (GDTCCTSupport) + +/** If YES, needs the network connection info field set during prioritization. + * @note Uses the GDTCOREvent customBytes property. + */ +@property(nonatomic) BOOL needsNetworkConnectionInfoPopulated; + +/** The network connection info as collected at the time of the event. + * @note Uses the GDTCOREvent customBytes property. + */ +@property(nullable, nonatomic) NSData *networkConnectionInfoData; + +/** Code that identifies the event to be sent to the CCT backend. + */ +@property(nullable, nonatomic) NSNumber *eventCode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/LICENSE b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/README.md b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/README.md new file mode 100644 index 00000000..d778205f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleDataTransportCCTSupport/README.md @@ -0,0 +1,311 @@ +[![Version](https://img.shields.io/cocoapods/v/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![License](https://img.shields.io/cocoapods/l/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) +[![Platform](https://img.shields.io/cocoapods/p/Firebase.svg?style=flat)](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`Example/Database/App/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/GoogleSignIn/.cocoapods.yml b/MyExperiences copy/Pods/GoogleSignIn/.cocoapods.yml new file mode 100755 index 00000000..64a82b1e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/.cocoapods.yml @@ -0,0 +1,5 @@ +try: + install: + pre: + - git clone https://github.com/googlesamples/google-services + project: 'google-services/ios/signin/SignInExample.xcodeproj' diff --git a/MyExperiences copy/Pods/GoogleSignIn/CHANGELOG.md b/MyExperiences copy/Pods/GoogleSignIn/CHANGELOG.md new file mode 100755 index 00000000..4c929073 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/CHANGELOG.md @@ -0,0 +1,132 @@ +# 2019-11-7 -- v5.0.2 +- Fixes the wrong error code being sent to `signIn:didSignInForUser:withError:` when the user + cancels iOS's consent dialog during the sign-in flow. + +# 2019-10-9 -- v5.0.1 +- Fixes an issue that the sign in flow cannot be correctly started on iOS 13. +- The zip distribution requires Xcode 11 or above. + +# 2019-8-14 -- v5.0.0 +- Changes to GIDSignIn + - `uiDelegate` has been replaced with `presentingViewController`. + - `hasAuthInKeychain` has been replaced with `hasPreviousSignIn`. + - `signInSilently` has been replaced with `restorePreviousSignIn`. + - Removed deprecated `kGIDSignInErrorCodeNoSignInHandlersInstalled` error code. +- Changes to GIDAuthentication + - Removed deprecated methods `getAccessTokenWithHandler:` and `refreshAccessTokenWithHandler:`. +- Changes to GIDGoogleUser + - Removed deprecated property `accessibleScopes`, use `grantedScopes` instead. +- Adds dependencies on AppAuth and GTMAppAuth. +- Removes the dependency on GoogleToolboxForMac. +- Drops support for iOS 7. + +# 2018-11-26 -- v4.4.0 +- Removes the dependency on GTM OAuth 2. + +# 2018-10-1 -- v4.3.0 +- Supports Google's Enterprise Mobile Management. + +# 2018-8-10 -- v4.2.0 +- Adds `grantedScopes` to `GIDGoogleUser`, allowing confirmation of which scopes + have been granted after a successful sign-in. +- Deprecates `accessibleScopes` in `GIDGoogleUser`, use `grantedScopes` instead. +- Localizes `GIDSignInButton` for hi (Hindi) and fr-CA (French (Canada)). +- Adds dependency to the system `LocalAuthentication` framework. + +# 2018-1-8 -- v4.1.2 +- Add `pod try` support for the GoogleSignIn CocoaPod. + +# 2017-10-17 -- v4.1.1 +- Fixes an issue that `GIDSignInUIDelegate`'s `signInWillDispatch:error:` was + not called on iOS 11. Please note that it is intended that neither + `signIn:presentViewController:` nor `signIn:dismissViewController:` is called + on iOS 11 because SFAuthenticationSession is not presented by the app's view + controller. + +# 2017-09-13 -- v4.1.0 +- Uses SFAuthenticationSession on iOS 11. + +# 2017-02-06 -- v4.0.2 +- No longer depends on GoogleAppUtilities. + +# 2016-10-24 -- v4.0.1 +- Switches to open source pod dependencies. +- Appearance of sign-in button no longer depends on requested scopes. + +# 2016-04-21 -- v4.0.0 +- GoogleSignIn pod now takes form of a static framework. Import with + `#import ` in Objective-C. +- Adds module support. You can also use `@import GoogleSignIn;` in Objective-C, + if module is enabled, and `import GoogleSignIn` in Swift without using a + bridge-header. +- For users of the stand-alone zip distribution, multiple frameworks are now + provided and all need to be added to a project. This decomposition allows more + flexibility in case of duplicated dependencies. +- Removes deprecated method `checkGoogleSignInAppInstalled` from `GIDSignIn`. +- Removes `allowsSignInWithBrowser` and `allowsSignInWithWebView` properties + from `GIDSignIn`. +- No longer requires adding bundle ID as a URL scheme supported by the app. + +# 2016-03-04 -- v3.0.0 +- Provides `givenName` and `familyName` properties on `GIDProfileData`. +- Allows setting the `loginHint` property on `GIDSignIn` to prefill the user's + ID or email address in the sign-in flow. +- Removed the `UIViewController(SignIn)` category as well as the `delegate` + property from `GIDSignInButton`. +- Requires that `uiDelegate` has been set properly on `GIDSignIn` and that + SafariServices framework has been linked. +- Removes the dependency on StoreKit. +- Provides bitcode support. +- Requires Xcode 7.0 or above due to bitcode incompatibilities with Xcode 6. + +# 2015-10-26 -- v2.4.0 +- Updates sign-in button with the new Google logo. +- Supports domain restriction for sign-in. +- Allows refreshing ID tokens. + +# 2015-10-09 -- v2.3.2 +- No longer requires Xcode 7. + +# 2015-10-01 -- v2.3.1 +- Fixes a crash in `GIDProfileData`'s `imageURLWithDimension:`. + +# 2015-09-25 -- v2.3.0 +- Requires Xcode 7.0 or above. +- Uses SFSafariViewController for signing in on iOS 9. `uiDelegate` must be + set for this to work. +- Optimizes fetching user profile. +- Supports GTMFetcherAuthorizationProtocol in GIDAuthentication. + +# 2015-07-15 -- v2.2.0 +- Compatible with iOS 9 (beta). Note that this version of the Sign-In SDK does + not include bitcode, so you must set ENABLE_BITCODE to NO in your project if + you use Xcode 7. +- Adds descriptive identifiers for GIDSignInButton's Auto Layout constraints. +- `signInSilently` no longer requires setting `uiDelegate`. + +# 2015-06-17 -- v2.1.0 +- Fixes Auto Layout issues with GIDSignInButton. +- Adds API to refresh access token in GIDAuthentication. +- Better exception description for unassigned clientID in GIDSignIn. +- Other minor bug fixes. + +# 2015-05-28 -- v2.0.1 +- Bug fixes + +# 2015-05-21 -- v2.0.0 +- Supports sign-in via UIWebView rather than app switching to a browser, + configurable with the new `allowsSignInWithWebView` property. +- Now apps which have disabled the app switch to a browser via the + `allowsSignInWithBrowser` and in-app web view via `allowsSignInWithWebView` + properties have the option to display a prompt instructing the user to + download the Google app from the App Store. +- Fixes sign-in button sizing issue when auto-layout is enabled +- `signInSilently` now calls the delegate with error when `hasAuthInKeychain` + is `NO` as documented +- Other minor bug fixes + +# 2015-03-12 -- v1.0.0 +- New sign-in focused SDK with refreshed API +- Dynamically rendered sign-in button with contextual branding +- Basic profile support +- Added allowsSignInWithBrowser property diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/GoogleSignIn b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/GoogleSignIn new file mode 100755 index 00000000..12c05067 Binary files /dev/null and b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/GoogleSignIn differ diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDAuthentication.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDAuthentication.h new file mode 100755 index 00000000..3571c6e8 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDAuthentication.h @@ -0,0 +1,65 @@ +/* + * GIDAuthentication.h + * Google Sign-In iOS SDK + * + * Copyright 2014 Google Inc. + * + * Use of this SDK is subject to the Google APIs Terms of Service: + * https://developers.google.com/terms/ + */ + +#import + +@protocol GTMFetcherAuthorizationProtocol; +@class GIDAuthentication; + +/// The callback block that takes a `GIDAuthentication`, or an error if attempt +/// to refresh was unsuccessful. +typedef void (^GIDAuthenticationHandler)(GIDAuthentication *authentication, NSError *error); + +/// The callback block that takes an access token, or an error if attempt to refresh was +/// unsuccessful. +typedef void (^GIDAccessTokenHandler)(NSString *accessToken, NSError *error); + +/// This class represents the OAuth 2.0 entities needed for sign-in. +@interface GIDAuthentication : NSObject + +/// The client ID associated with the authentication. +@property(nonatomic, readonly) NSString *clientID; + +/// The OAuth2 access token to access Google services. +@property(nonatomic, readonly) NSString *accessToken; + +/// The estimated expiration date of the access token. +@property(nonatomic, readonly) NSDate *accessTokenExpirationDate; + +/// The OAuth2 refresh token to exchange for new access tokens. +@property(nonatomic, readonly) NSString *refreshToken; + +/// An OpenID Connect ID token that identifies the user. Send this token to your server to +/// authenticate the user there. For more information on this topic, see +/// https://developers.google.com/identity/sign-in/ios/backend-auth +@property(nonatomic, readonly) NSString *idToken; + +/// The estimated expiration date of the ID token. +@property(nonatomic, readonly) NSDate *idTokenExpirationDate; + +/// Gets a new authorizer for `GTLService`, `GTMSessionFetcher`, or `GTMHTTPFetcher`. +/// +/// @return A new authorizer +- (id)fetcherAuthorizer; + +/// Get a valid access token and a valid ID token, refreshing them first if they have expired or are +/// about to expire. +/// +/// @param handler A callback block that takes a `GIDAuthentication`, or an +/// error if attempt to refresh was unsuccessful. +- (void)getTokensWithHandler:(GIDAuthenticationHandler)handler; + +/// Refreshes the access token and the ID token using the refresh token. +/// +/// @param handler A callback block that takes a `GIDAuthentication`, or an +/// error if attempt to refresh was unsuccessful. +- (void)refreshTokensWithHandler:(GIDAuthenticationHandler)handler; + +@end diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDGoogleUser.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDGoogleUser.h new file mode 100755 index 00000000..17e6e5ea --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDGoogleUser.h @@ -0,0 +1,39 @@ +/* + * GIDGoogleUser.h + * Google Sign-In iOS SDK + * + * Copyright 2014 Google Inc. + * + * Use of this SDK is subject to the Google APIs Terms of Service: + * https://developers.google.com/terms/ + */ + +#import + +@class GIDAuthentication; +@class GIDProfileData; + +/// This class represents a user account. +@interface GIDGoogleUser : NSObject + +/// The Google user ID. +@property(nonatomic, readonly) NSString *userID; + +/// Representation of the Basic profile data. It is only available if +/// `GIDSignIn.shouldFetchBasicProfile` is set and either `-[GIDSignIn signIn]` or +/// `-[GIDSignIn restorePreviousSignIn]` has been completed successfully. +@property(nonatomic, readonly) GIDProfileData *profile; + +/// The authentication object for the user. +@property(nonatomic, readonly) GIDAuthentication *authentication; + +/// The API scopes granted to the app in an array of `NSString`. +@property(nonatomic, readonly) NSArray *grantedScopes; + +/// For Google Apps hosted accounts, the domain of the user. +@property(nonatomic, readonly) NSString *hostedDomain; + +/// An OAuth2 authorization code for the home server. +@property(nonatomic, readonly) NSString *serverAuthCode; + +@end diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDProfileData.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDProfileData.h new file mode 100755 index 00000000..f07d4752 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDProfileData.h @@ -0,0 +1,37 @@ +/* + * GIDProfileData.h + * Google Sign-In iOS SDK + * + * Copyright 2014 Google Inc. + * + * Use of this SDK is subject to the Google APIs Terms of Service: + * https://developers.google.com/terms/ + */ + +#import + +/// This class represents the basic profile information of a `GIDGoogleUser`. +@interface GIDProfileData : NSObject + +/// The Google user's email. +@property(nonatomic, readonly) NSString *email; + +/// The Google user's full name. +@property(nonatomic, readonly) NSString *name; + +/// The Google user's given name. +@property(nonatomic, readonly) NSString *givenName; + +/// The Google user's family name. +@property(nonatomic, readonly) NSString *familyName; + +/// Whether or not the user has profile image. +@property(nonatomic, readonly) BOOL hasImage; + +/// Gets the user's profile image URL for the given dimension in pixels for each side of the square. +/// +/// @param dimension The desired height (and width) of the profile image. +/// @return The URL of the user's profile image. +- (NSURL *)imageURLWithDimension:(NSUInteger)dimension; + +@end diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignIn.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignIn.h new file mode 100755 index 00000000..12046159 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignIn.h @@ -0,0 +1,170 @@ +/* + * GIDSignIn.h + * Google Sign-In iOS SDK + * + * Copyright 2012 Google Inc. + * + * Use of this SDK is subject to the Google APIs Terms of Service: + * https://developers.google.com/terms/ + */ + +#import +#import + +@class GIDGoogleUser; +@class GIDSignIn; + +/// The error domain for `NSError`s returned by the Google Identity SDK. +extern NSString *const kGIDSignInErrorDomain; + +/// A list of potential error codes returned from the Google Identity SDK. +typedef NS_ENUM(NSInteger, GIDSignInErrorCode) { + /// Indicates an unknown error has occurred. + kGIDSignInErrorCodeUnknown = -1, + /// Indicates a problem reading or writing to the application keychain. + kGIDSignInErrorCodeKeychain = -2, + /// Indicates there are no valid auth tokens in the keychain. This error code will be returned by + /// `restorePreviousSignIn` if the user has not signed in before or if they have since signed out. + kGIDSignInErrorCodeHasNoAuthInKeychain = -4, + /// Indicates the user canceled the sign in request. + kGIDSignInErrorCodeCanceled = -5, + /// Indicates an Enterprise Mobility Management related error has occurred. + kGIDSignInErrorCodeEMM = -6, +}; + +/// A protocol implemented by the delegate of `GIDSignIn` to receive a refresh token or an error. +@protocol GIDSignInDelegate + +/// The sign-in flow has finished and was successful if `error` is `nil`. +- (void)signIn:(GIDSignIn *)signIn + didSignInForUser:(GIDGoogleUser *)user + withError:(NSError *)error; + +@optional + +/// Finished disconnecting `user` from the app successfully if `error` is `nil`. +- (void)signIn:(GIDSignIn *)signIn + didDisconnectWithUser:(GIDGoogleUser *)user + withError:(NSError *)error; + +@end + +/// This class signs the user in with Google. It also provides single sign-on via a capable Google +/// app if one is installed. +/// +/// For reference, please see "Google Sign-In for iOS" at +/// https://developers.google.com/identity/sign-in/ios +/// +/// Here is sample code to use `GIDSignIn`: +/// 1. Get a reference to the `GIDSignIn` shared instance: +/// ``` +/// GIDSignIn *signIn = [GIDSignIn sharedInstance]; +/// ``` +/// 2. Call `[signIn setDelegate:self]`; +/// 3. Set up delegate method `signIn:didSignInForUser:withError:`. +/// 4. Call `handleURL` on the shared instance from `application:openUrl:...` in your app delegate. +/// 5. Call `signIn` on the shared instance; +@interface GIDSignIn : NSObject + +/// The authentication object for the current user, or `nil` if there is currently no logged in +/// user. +@property(nonatomic, readonly) GIDGoogleUser *currentUser; + +/// The object to be notified when authentication is finished. +@property(nonatomic, weak) id delegate; + +/// The view controller used to present `SFSafariViewContoller` on iOS 9 and 10. +@property(nonatomic, weak) UIViewController *presentingViewController; + +/// The client ID of the app from the Google APIs console. Must set for sign-in to work. +@property(nonatomic, copy) NSString *clientID; + +/// The API scopes requested by the app in an array of `NSString`s. The default value is `@[]`. +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSArray *scopes; + +/// Whether or not to fetch basic profile data after signing in. The data is saved in the +/// `GIDGoogleUser.profileData` object. +/// +/// Setting the flag will add "email" and "profile" to scopes. +/// Defaults to `YES`. +@property(nonatomic, assign) BOOL shouldFetchBasicProfile; + +/// The language for sign-in, in the form of ISO 639-1 language code optionally followed by a dash +/// and ISO 3166-1 alpha-2 region code, such as `@"it"` or `@"pt-PT"`. Only set if different from +/// system default. +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSString *language; + +/// The login hint to the authorization server, for example the user's ID, or email address, +/// to be prefilled if possible. +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSString *loginHint; + +/// The client ID of the home web server. This will be returned as the `audience` property of the +/// OpenID Connect ID token. For more info on the ID token: +/// https://developers.google.com/identity/sign-in/ios/backend-auth +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSString *serverClientID; + +/// The OpenID2 realm of the home web server. This allows Google to include the user's OpenID +/// Identifier in the OpenID Connect ID token. +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSString *openIDRealm; + +/// The Google Apps domain to which users must belong to sign in. To verify, check +/// `GIDGoogleUser`'s `hostedDomain` property. +/// +/// This property is optional. If you set it, set it before calling `signIn`. +@property(nonatomic, copy) NSString *hostedDomain; + +/// Returns a shared `GIDSignIn` instance. ++ (GIDSignIn *)sharedInstance; + +/// Unavailable. Use `sharedInstance` to instantiate `GIDSignIn`. ++ (instancetype)new NS_UNAVAILABLE; + +/// Unavailable. Use `sharedInstance` to instantiate `GIDSignIn`. +- (instancetype)init NS_UNAVAILABLE; + +/// This method should be called from your `UIApplicationDelegate`'s `application:openURL:options` +/// and `application:openURL:sourceApplication:annotation` method(s). +/// +/// @param url The URL that was passed to the app. +/// @return `YES` if `GIDSignIn` handled this URL. +- (BOOL)handleURL:(NSURL *)url; + +/// Checks if there is a previously authenticated user saved in keychain. +/// +/// @return `YES` if there is a previously authenticated user saved in keychain. +- (BOOL)hasPreviousSignIn; + +/// Attempts to restore a previously authenticated user without interaction. + +/// The delegate will be +/// called at the end of this process indicating success or failure. The current values of +/// `GIDSignIn`'s configuration properties will not impact the restored user. +- (void)restorePreviousSignIn; + +/// Starts an interactive sign-in flow using `GIDSignIn`'s configuration properties. +/// +/// The delegate +/// will be called at the end of this process. Any saved sign-in state will be replaced by the +/// result of this flow. Note that this method should not be called when the app is starting up, +/// (e.g in `application:didFinishLaunchingWithOptions:`); instead use the `restorePreviousSignIn` +/// method to restore a previous sign-in. +- (void)signIn; + +/// Marks current user as being in the signed out state. +- (void)signOut; + +/// Disconnects the current user from the app and revokes previous authentication. If the operation +/// succeeds, the OAuth 2.0 token is also removed from keychain. +- (void)disconnect; + +@end diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignInButton.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignInButton.h new file mode 100755 index 00000000..795f5698 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GIDSignInButton.h @@ -0,0 +1,53 @@ +/* + * GIDSignInButton.h + * Google Sign-In iOS SDK + * + * Copyright 2012 Google Inc. + * + * Use of this SDK is subject to the Google APIs Terms of Service: + * https://developers.google.com/terms/ + */ + +#import + +/// The layout styles supported by the `GIDSignInButton`. +/// +/// The minimum size of the button depends on the language used for text. +/// The following dimensions (in points) fit for all languages: +/// - kGIDSignInButtonStyleStandard: 230 x 48 +/// - kGIDSignInButtonStyleWide: 312 x 48 +/// - kGIDSignInButtonStyleIconOnly: 48 x 48 (no text, fixed size) +typedef NS_ENUM(NSInteger, GIDSignInButtonStyle) { + kGIDSignInButtonStyleStandard = 0, + kGIDSignInButtonStyleWide = 1, + kGIDSignInButtonStyleIconOnly = 2 +}; + +/// The color schemes supported by the `GIDSignInButton`. +typedef NS_ENUM(NSInteger, GIDSignInButtonColorScheme) { + kGIDSignInButtonColorSchemeDark = 0, + kGIDSignInButtonColorSchemeLight = 1 +}; + +/// This class provides the "Sign in with Google" button. +/// +/// You can instantiate this class programmatically or from a NIB file. You +/// should set up the `GIDSignIn` shared instance with your client ID and any +/// additional scopes, implement the delegate methods for `GIDSignIn`, and add +/// this button to your view hierarchy. +@interface GIDSignInButton : UIControl + +/// The layout style for the sign-in button. +/// Possible values: +/// - kGIDSignInButtonStyleStandard: 230 x 48 (default) +/// - kGIDSignInButtonStyleWide: 312 x 48 +/// - kGIDSignInButtonStyleIconOnly: 48 x 48 (no text, fixed size) +@property(nonatomic, assign) GIDSignInButtonStyle style; + +/// The color scheme for the sign-in button. +/// Possible values: +/// - kGIDSignInButtonColorSchemeDark +/// - kGIDSignInButtonColorSchemeLight (default) +@property(nonatomic, assign) GIDSignInButtonColorScheme colorScheme; + +@end diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GoogleSignIn.h b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GoogleSignIn.h new file mode 100755 index 00000000..8ccf7cd2 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Headers/GoogleSignIn.h @@ -0,0 +1,5 @@ +#import "GIDAuthentication.h" +#import "GIDGoogleUser.h" +#import "GIDProfileData.h" +#import "GIDSignIn.h" +#import "GIDSignInButton.h" diff --git a/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Modules/module.modulemap b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Modules/module.modulemap new file mode 100755 index 00000000..421acdc9 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Frameworks/GoogleSignIn.framework/Modules/module.modulemap @@ -0,0 +1,13 @@ +framework module GoogleSignIn { + umbrella header "GoogleSignIn.h" + export * + module * { export * } + link framework "AuthenticationServices" + link framework "CoreGraphics" + link framework "CoreText" + link framework "Foundation" + link framework "LocalAuthentication" + link framework "SafariServices" + link framework "Security" + link framework "UIKit" +} diff --git a/MyExperiences copy/Pods/GoogleSignIn/README.md b/MyExperiences copy/Pods/GoogleSignIn/README.md new file mode 100755 index 00000000..4418b664 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/README.md @@ -0,0 +1,18 @@ +# Google Sign-In SDK for iOS + +The Google Sign-In SDK allows users to sign in with their Google account from +third-party apps. + +Please visit [our developer site](https://developers.google.com/identity/sign-in/ios/) +for integration instructions, documentation, support information, and terms of +service. + +## Getting Started + +* Try our example app with: + ``` + $ pod try GoogleSignIn + ``` + and follow the directions [here](https://developers.google.com/identity/sign-in/ios/start). +* Read our [getting started guides](https://developers.google.com/identity/sign-in/ios/start-integrating). +* Take a look at the [API reference](https://developers.google.com/identity/sign-in/ios/api/). diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Info.plist b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Info.plist new file mode 100755 index 00000000..290d5343 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIconFile + + CFBundleIdentifier + com.google.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Roboto-Bold.ttf b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Roboto-Bold.ttf new file mode 100755 index 00000000..68822caf Binary files /dev/null and b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/Roboto-Bold.ttf differ diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ar.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ar.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..0f0b1766 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ar.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "تسجيل الدخول"; + +/* Long form sign-in button text */ +"Sign in with Google" = "تسجيل الدخول باستخدام Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "تسجيل الدخول باستخدام Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "احصل على تطبيق Google المجاني وسجل الدخول إلى التطبيقات من خلال حساب Google. لا توجد حاجة لتذكر كلمات المرور."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "إلغاء"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "جلب"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "موافق"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "إلغاء"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "إعدادات"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "يتعذَّر تسجيل الدخول إلى الحساب"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "يطلب منك المشرف تعيين رمز مرور على هذا الجهاز للدخول إلى هذا الحساب. يُرجى تعيين رمز المرور وإعادة المحاولة."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "لا يتوافق هذا الجهاز مع سياسة الأمان التي أعدها مشرفك"; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "هل تريد الربط بتطبيق Device Policy؟"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "يجب الربط مع تطبيق Device Policy قبل تسجيل الدخول لحماية بيانات مؤسستك."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "ربط"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ca.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ca.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..f5cdb308 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ca.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Inicia la sessió"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Inicia la sessió amb Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Inicia la sessió amb Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Obteniu l'aplicació Google gratuïta i inicieu la sessió a les aplicacions amb el vostre compte de Google. D'aquesta manera, ja no haureu de recordar cap més contrasenya."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancel·la"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Obtén"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "D’acord"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancel·la"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Configuració"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "No es pot iniciar la sessió al compte"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "L'administrador requereix que estableixis una contrasenya en aquest dispositiu per accedir al compte. Estableix una contrasenya i torna-ho a provar."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "El dispositiu no compleix la política de seguretat establerta pel teu administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vols connectar-te amb l'aplicació Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Per protegir les dades de la teva organització, t'has de connectar amb l'aplicació Device Policy abans d'iniciar la sessió."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Vull connectar-me"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/cs.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/cs.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..43f2c8b6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/cs.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Přihlásit se"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Přihlásit se účtem Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Přihlašujte se účtem Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Nainstalujte si zdarma aplikaci Google a přihlašujte se do aplikací pomocí účtu Google. Nebudete si už muset pamatovat spoustu hesel."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Zrušit"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Instalovat"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Zrušit"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Nastavení"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Nelze se přihlásit k účtu"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administrátor vyžaduje, abyste v tomto zařízení nastavili heslo pro přístup k tomuto účtu. Nastavte prosím heslo a zkuste to znovu."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Zařízení nevyhovuje bezpečnostním zásadám nastaveným administrátorem."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Propojit s aplikací Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Aby bylo možné chránit data vaší organizace, před přihlášením je nutné aktivovat propojení s aplikací Device Policy."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Propojit"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/da.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/da.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..22d5f52f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/da.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Log ind"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Log ind med Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Log ind med Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Hent den gratis Google-app, og log ind på apps med din Google-konto. Du slipper for at huske på adgangskoder."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Annuller"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Hent"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Annuller"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Indstillinger"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Der kunne ikke logges ind på kontoen"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Din administrator kræver, at du angiver en adgangskode på enheden for at få adgang til kontoen. Angiv en adgangskode, og prøv igen."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Enheden overholder ikke den sikkerhedspolitik, der er angivet af din administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vil du oprette forbindelse til appen Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Du skal oprette forbindelse til appen Device Policy, inden du logger ind, for at beskytte din organisations data."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Opret forbindelse"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/de.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/de.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..2a26c4bd --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/de.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Anmelden"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Über Google anmelden"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Über Google anmelden"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Installieren Sie die kostenlose Google App und melden Sie sich mit Ihrem Google-Konto in Apps an. So müssen Sie sich keine Passwörter mehr merken."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Abbrechen"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Installieren"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Abbrechen"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Einstellungen"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Anmelden im Konto nicht möglich"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Ihr Administrator hat festgelegt, dass auf diesem Gerät ein Sicherheitscode eingerichtet werden muss, um auf dieses Konto zuzugreifen. Bitte legen Sie einen Sicherheitscode fest und versuchen Sie es noch einmal."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Das Gerät ist nicht mit den von Ihrem Administrator festgelegten Sicherheitsrichtlinien konform."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Mit der Device Policy App verknüpfen?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Zum Schutz der Daten Ihrer Organisation müssen Sie Ihr Gerät zuerst mit der Device Policy App verknüpfen, bevor Sie sich anmelden."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Verknüpfen"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/el.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/el.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..284db52e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/el.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Σύνδεση"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Συνδεθείτε με το Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Συνδεθείτε με το Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Αποκτήστε τη δωρεάν εφαρμογή Google και συνδεθείτε σε εφαρμογές με το Λογαριασμό σας Google. Δεν χρειάζεται να απομνημονεύετε κωδικούς πρόσβασης."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Ακύρωση"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Λήψη"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "ΟΚ"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Άκυρο"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Ρυθμίσεις"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Δεν είναι δυνατή η σύνδεση στον λογαριασμό"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Ο διαχειριστής σας απαιτεί να ορίσετε έναν κωδικό πρόσβασης στη συσκευή, για να έχετε πρόσβαση σε αυτόν τον λογαριασμό. Ορίστε έναν κωδικό πρόσβασης και δοκιμάστε ξανά."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Η συσκευή δεν συμμορφώνεται με την πολιτική ασφαλείας που έχει ορίσει ο διαχειριστής σας."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Σύνδεση με την εφαρμογή Device Policy;"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Προκειμένου να προστατεύσετε τα δεδομένα του οργανισμού σας, θα πρέπει να συνδεθείτε με την εφαρμογή Device Policy προτού συνδεθείτε στον λογαριασμό σας."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Σύνδεση"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..460ad64a --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en.lproj/GoogleSignIn.strings @@ -0,0 +1,32 @@ +/* Sign-in button text */ +"Sign in" = "Sign in"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Sign in with Google"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancel"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Settings"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Unable to sign in to account"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Your administrator requires you to set a passcode on this device to access this account. Please set a passcode and try again."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "The device is not compliant with the security policy set by your administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Connect with Device Policy App?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "In order to protect your organization's data, you must connect with the Device Policy app before logging in."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Connect"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en_GB.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en_GB.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..402dbe56 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/en_GB.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Sign in"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Sign in with Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Sign in with Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Get the free Google app and sign in to apps with your Google Account. No need to remember passwords."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancel"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Get"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancel"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Settings"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Unable to sign in to account"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Your administrator requires you to set a passcode on this device to access this account. Please set a passcode and try again."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "The device is not compliant with the security policy set by your administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Connect with Device Policy App?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "In order to protect your organisation's data, you must connect with the Device Policy app before logging in."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Connect"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..f13de7b6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Iniciar sesión"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Iniciar sesión con Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Iniciar sesión con Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Obtén la aplicación Google gratuita e inicia sesión en aplicaciones con tu cuenta de Google. No tendrás que recordar las contraseñas."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancelar"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Obtener"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "Aceptar"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancelar"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Configuración"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "No se ha podido iniciar sesión en la cuenta"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "El administrador requiere que configures una contraseña en este dispositivo para acceder a esta cuenta. Inténtalo de nuevo cuando lo hayas hecho."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "El dispositivo no cumple la política de privacidad que ha definido tu administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "¿Has conectado tu dispositivo con la aplicación Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Para proteger los datos de tu organización, debes conectar tu dispositivo con la aplicación Device Policy antes de iniciar sesión."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Conectar"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es_MX.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es_MX.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..12a2892f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/es_MX.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Acceder"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Acceder con Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Acceder con Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Obtén Google app y accede a aplicaciones con tu cuenta de Google. No hace falta recordar contraseñas."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancelar"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Obtener"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "Aceptar"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancelar"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Configuración"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "No es posible acceder a la cuenta"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Para acceder a esta cuenta, tu administrador requiere que establezcas una contraseña en el dispositivo. Configúrala y vuelve a intentarlo."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "El dispositivo no cumple con la política de seguridad que estableció el administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "¿Deseas conectarte con la app de Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Para proteger los datos de tu organización, debes conectarte con la app de Device Policy antes de acceder."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Conectar"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fi.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fi.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..0134a2cd --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fi.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Kirjaudu sisään"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Kirjaudu Google-tilin tunnuksilla"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Kirjaudu Google-tilin tunnuksilla"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Hanki ilmainen Google-sovellus ja kirjaudu sovelluksiin Google-tililläsi. Sinun ei tarvitse muistaa salasanoja."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Peruuta"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Hae"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Peruuta"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Asetukset"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Kirjautuminen tilille ei onnistu"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Järjestelmänvalvoja edellyttää tunnuskoodin määrittämistä, ennen kuin voit käyttää tiliä tällä laitteella. Määritä tunnuskoodi ja yritä uudelleen."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Laite ei noudata järjestelmänvalvojan määrittämää verkkotunnuskäytäntöä."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Muodostetaanko yhteys Device Policy ‑sovellukseen?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Suojaa organisaatiosi dataa muodostamalla yhteys Device Policy ‑sovellukseen ennen kirjautumista."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Muodosta yhteys"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..96b921ee --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Se connecter"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Se connecter avec Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Se connecter avec Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Installez l'appli Google gratuite et connectez-vous à des applications avec votre compte Google. Plus besoin de vous souvenir de vos mots de passe."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Annuler"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Installer"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Annuler"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Paramètres"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Impossible de se connecter au compte"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Votre administrateur exige que vous définissiez un mot de passe sur cet appareil pour accéder à ce compte. Veuillez définir un mot de passe, puis réessayer."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "L'appareil ne respecte pas les règles de sécurité définies par votre administrateur."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Se connecter à l'application Device Policy ?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Afin de protéger les données de votre organisation, vous devez vous connecter à l'application Device Policy avant de vous connecter à votre compte."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Connexion"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr_CA.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr_CA.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..532d63e5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/fr_CA.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Se connecter"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Se connecter à Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Connectez-vous à Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Téléchargez gratuitement l'application Google et connectez-vous à des applications avec votre compte Google. Plus besoin de mémoriser vos mots de passe."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Annuler"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Télécharger"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Annuler"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Paramètres"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Impossible de se connecter au compte"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Pour que votre administrateur puisse accéder à ce compte, vous devez définir un mot de passe sur cet appareil. Veuillez définir un mot de passe et réessayer."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "L'appareil n'est pas conforme à la politique de sécurité définie par votre administrateur."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Connexion avec l'application Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Pour protéger les données de votre organisation, vous devez vous connecter à l'application Device Policy avant de vous connecter."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Connexion"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google.png b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google.png new file mode 100755 index 00000000..26f15cb3 Binary files /dev/null and b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google.png differ diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@2x.png b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@2x.png new file mode 100755 index 00000000..26edd541 Binary files /dev/null and b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@2x.png differ diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@3x.png b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@3x.png new file mode 100755 index 00000000..d978ed26 Binary files /dev/null and b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/google@3x.png differ diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/he.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/he.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..efd53fef --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/he.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "היכנס"; + +/* Long form sign-in button text */ +"Sign in with Google" = "היכנס באמצעות Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "כניסה באמצעות Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "התקן את Google app בחינם והיכנס אל אפליקציות באמצעות חשבון Google. לא תצטרך עוד לזכור סיסמאות."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "בטל"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "התקן"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "אישור"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "ביטול"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "הגדרות"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "לא ניתן להיכנס לחשבון"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "מנהל המערכת דורש ממך להגדיר קוד סיסמה במכשיר זה כדי לגשת לחשבון זה. יש להגדיר קוד סיסמה ולנסות שוב."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "המכשיר אינו פועל בהתאם למדיניות האבטחה שנקבעה על-ידי מנהל המערכת."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "האם להתחבר באמצעות האפליקציית Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "על מנת להגן על נתוני הארגון שלך, יש להתחבר באמצעות אפליקציית Device Policy לפני הכניסה לחשבון."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "התחברות"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hi.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hi.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..3b7cd1ff --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hi.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "साइन इन करें"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Google के साथ साइन इन करें"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Google के साथ साइन इन करें"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "मुफ़्त Google ऐप्लिकेशन पाएं और अपने Google खाते से ऐप्लिकेशन में साइन इन करें. पासवर्ड याद रखने की ज़रूरत नहीं."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "अभी नहीं"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "पाएं"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "ठीक"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "अभी नहीं"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "सेटिंग"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "खाते में साइन इन नहीं किया जा सका"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "आपके एडमिन के लिए ज़रूरी है कि आप यह खाता एक्सेस करने के लिए इस डिवाइस पर एक पासकोड सेट करें. कृपया पासकोड सेट करें और दोबारा कोशिश करें."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "डिवाइस आपके एडमिन के ज़रिए सेट की गई सुरक्षा नीति का अनुपालन नहीं करता है."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "क्या Device Policy ऐप्लिकेशन से कनेक्ट करना चाहते हैं?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "अपने संगठन डेटा की सुरक्षा के लिए, आपको लॉग-इन करने से पहले Device Policy ऐप्लिकेशन से कनेक्ट करना होगा."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "कनेक्ट करें"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hr.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hr.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..32b6cc3d --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hr.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Prijava"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Prijavite se putem Googlea"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Prijavite se putem Googlea"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Preuzmite besplatnu aplikaciju Google i prijavljujte se na aplikacije svojim Google računom. Ne morate pamtiti zaporke."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Odustani"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Nabavi"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "U redu"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Odbaci"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Postavke"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Prijava na račun nije moguća"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Vaš administrator zahtijeva da postavite šifru zaporke na ovom uređaju da biste pristupili računu. Postavite šifru zaporke i pokušajte ponovo."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Uređaj nije usklađen sa sigurnosnim pravilima koja je postavio vaš administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Želite li se povezati s aplikacijom Pravila za uređaje?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Da biste zaštitili podatke svoje organizacije, morate se povezati s aplikacijom Pravila za uređaje prije prijave."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Poveži"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hu.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hu.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..9359cf51 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/hu.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Bejelentkezés"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Bejelentkezés Google-fiókkal"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Bejelentkezés Google-fiókkal"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Telepítse az ingyenes Google alkalmazást, és jelentkezzen be az egyes termékekbe Google-fiókjával. Nem kell különböző jelszavakat megjegyeznie."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Mégse"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Telepítés"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Mégse"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Beállítások"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Nem sikerült bejelentkezni a fiókba"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Adminisztrátora biztonsági kód beállítását kéri ezen az eszközön a fiókhoz való hozzáféréshez. Kérjük, állítson be biztonsági kódot, majd próbálja újra."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Az eszköz nem felel meg a rendszergazda által beállított biztonsági házirendnek."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Csatlakozik a Device Policy alkalmazáshoz?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "A szervezet adatainak védelme érdekében a bejelentkezés előtt csatlakoznia kell a Device Policy alkalmazáshoz."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Csatlakozás"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/id.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/id.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..9b66ca3c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/id.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Masuk"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Masuk dengan Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Masuk dengan Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Dapatkan Google app gratis dan masuk ke aplikasi dengan Akun Google. Tidak perlu mengingat sandi."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Batal"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Ambil"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "Oke"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Batal"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Setelan"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Tidak dapat login ke akun"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administrator mengharuskan Anda menyetel kode sandi di perangkat ini untuk mengakses akun ini. Setel kode sandi dan coba lagi."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Perangkat ini tidak sesuai dengan kebijakan keamanan yang disetel oleh administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Sambungkan dengan Aplikasi Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Untuk melindungi data organisasi, Anda harus tersambung dengan aplikasi Device Policy sebelum login."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Sambungkan"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/it.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/it.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..9c3e576a --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/it.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Accedi"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Accedi con Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Accedi con Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Scarica gratis l'app Google app e accedi alle app con il tuo account Google: liberati dai vincoli delle password."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Annulla"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Scarica"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Annulla"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Impostazioni"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Impossibile accedere all'account"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "L'amministratore richiede l'impostazione di un passcode sul dispositivo per accedere a questo account. Imposta un passcode e riprova."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Il dispositivo non è conforme alle norme di sicurezza stabilite dall'amministratore."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vuoi collegarti all'app Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Per proteggere i dati della tua organizzazione, devi collegarti all'app Device Policy prima di accedere."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Collega"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ja.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ja.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..6dab02ca --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ja.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "ログイン"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Googleでログイン"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Googleでログイン"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "無料のGoogleアプリをインストールして、Googleアカウントでアプリにログインしよう。パスワードを覚えておく必要はありません。"; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "キャンセル"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "インストール"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "キャンセル"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "設定"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "アカウントにログインできません"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "このアカウントにアクセスするには、この端末でパスコードを設定する必要があります。パスコードを設定してから、もう一度お試しください。"; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "この端末は、管理者が設定したセキュリティ ポリシーに準拠していません。"; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Device Policy アプリと接続しますか?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "組織のデータを保護するために、ログインする前に Device Policy アプリと接続する必要があります。"; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "接続"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ko.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ko.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..b596605d --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ko.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "로그인"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Google 계정으로 로그인"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Google 계정으로 로그인"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "무료 Google 앱을 다운로드하여 Google 계정으로 앱에 로그인하세요. 비밀번호를 기억할 필요가 없습니다."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "취소"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "설치"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "확인"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "취소"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "설정"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "계정에 로그인할 수 없음"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "관리자의 설정에 따라 이 계정에 액세스하려면 사용 중인 기기에 비밀번호를 설정해야 합니다. 비밀번호를 설정한 후 다시 시도해 주세요."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "관리자가 설정한 보안 정책을 준수하지 않는 기기입니다."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Device Policy 앱과 연결하시겠습니까?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "조직의 데이터를 보호하려면 로그인하기 전에 Device Policy 앱과 연결해야 합니다."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "연결"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ms.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ms.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..700aaf2c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ms.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Log masuk"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Log masuk dengan Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Log masuk dengan Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Dapatkan apl Google percuma dan log masuk ke apl menggunakan Akaun Google anda. Tidak perlu mengingati kata laluan."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Batal"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Dapatkan"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Batal"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Tetapan"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Tidak dapat log masuk ke akaun"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Pentadbir menghendaki anda menetapkan kod laluan pada peranti ini untuk mengakses akaun ini. Sila tetapkan kod laluan, kemudian cuba lagi."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Peranti tidak mematuhi dasar keselamatan yang ditetapkan oleh pentadbir anda."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Berhubung dengan Apl Dasar Peranti?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Untuk melindungi data organisasi anda, anda mesti berhubung dengan apl Dasar Peranti sebelum log masuk."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Hubungkan"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nb.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nb.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..994b40ff --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nb.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Logg på"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Logg på med Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Logg på med Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Skaff deg den gratis Google-appen, og logg på apper med Google-kontoen din. Du trenger ikke å huske passord."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Avbryt"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Hent"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Avbryt"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Innstillinger"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Kan ikke logge på kontoen"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administratoren din krever at du angir en adgangskode på denne enheten for å få tilgang til kontoen. Angi en adgangskode, og prøv på nytt."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Enheten overholder ikke retningslinjene for sikkerhet som ble angitt av administratoren din."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vil du koble til med Device Policy-appen?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "For å beskytte dataene til organisasjonen din må du koble til med Device Policy-appen før du logger på."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Koble til"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nl.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nl.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..fb539e08 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/nl.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Inloggen"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Inloggen met Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Inloggen met Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Installeer de gratis Google-app en log in bij apps met uw Google-account. U hoeft geen wachtwoorden te onthouden."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Annuleren"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Installeren"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Annuleren"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Instellingen"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Kan niet inloggen op account"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Uw beheerder vereist dat u een toegangscode instelt op dit apparaat om toegang te krijgen tot dit account. Stel een toegangscode in en probeer het opnieuw."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Het apparaat voldoet niet aan het beveiligingsbeleid dat is ingesteld door uw beheerder."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Verbinden met Device Policy-app?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Ter bescherming van de gegevens van uw organisatie moet u verbinding maken met de Device Policy-app voordat u inlogt."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Verbinden"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pl.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pl.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..6ed4b576 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pl.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Zaloguj się"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Zaloguj się przez Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Zaloguj się przez Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Pobierz darmową aplikację Google i zaloguj się do aplikacji, używając konta Google. Nie musisz pamiętać haseł."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Anuluj"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Pobierz"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Anuluj"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Ustawienia"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Nie można zalogować się na konto"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administrator wymaga ustawienia kodu dostępu do konta na tym urządzeniu. Ustaw kod dostępu i spróbuj ponownie."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Urządzenie nie jest zgodne z zasadami bezpieczeństwa ustanowionymi przez Twojego administratora."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Połączyć z aplikacją Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Aby chronić dane organizacji, przed zalogowaniem musisz się połączyć z aplikacją Device Policy."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Połącz"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..3207312c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Fazer login"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Fazer login com o Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Fazer login com o Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Faça o download do Google app gratuitamente e faça login em aplicativos com sua Conta do Google. Não há necessidade de lembrar senhas."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancelar"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Instalar"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancelar"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Configurações"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Não foi possível fazer login na conta"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Seu administrador exige que você defina uma senha neste dispositivo para acessar esta conta. Defina uma senha e tente novamente."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "O dispositivo não está em conformidade com a política de segurança definida pelo administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Conectar-se ao app Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Para proteger os dados da sua organização, você precisa se conectar ao app Device Policy antes de fazer login."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Conectar"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_BR.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_BR.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..3207312c --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_BR.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Fazer login"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Fazer login com o Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Fazer login com o Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Faça o download do Google app gratuitamente e faça login em aplicativos com sua Conta do Google. Não há necessidade de lembrar senhas."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancelar"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Instalar"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancelar"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Configurações"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Não foi possível fazer login na conta"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Seu administrador exige que você defina uma senha neste dispositivo para acessar esta conta. Defina uma senha e tente novamente."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "O dispositivo não está em conformidade com a política de segurança definida pelo administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Conectar-se ao app Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Para proteger os dados da sua organização, você precisa se conectar ao app Device Policy antes de fazer login."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Conectar"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_PT.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_PT.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..91d7a258 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/pt_PT.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Iniciar sessão"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Iniciar sessão com o Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Iniciar sessão com o Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Obtenha a aplicação Google gratuita e inicie sessão nas aplicações com a sua Conta Google. Não precisa de memorizar palavras-passe."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Cancelar"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Obter"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Cancelar"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Definições"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Não é possível iniciar sessão na conta"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "O administrador requer a definição de um código secreto neste dispositivo para aceder a esta conta. Defina um código secreto e tente novamente."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "O dispositivo não está em conformidade com a política de segurança definida pelo seu administrador."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Pretende ligar-se à aplicação Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Para proteger os dados da sua entidade, tem de se ligar à aplicação Device Policy antes de iniciar sessão."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Ligar"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ro.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ro.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..34b4239e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ro.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Conectați-vă"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Conectați-vă cu Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Conectați-vă cu Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Instalați aplicația Google gratuită și conectați-vă la aplicații folosind Contul Google. Nu mai trebuie să rețineți parolele."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Anulați"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Instalați"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Anulați"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Setări"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Nu vă puteți conecta la cont"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administratorul impune să setați o parolă pe acest dispozitiv ca să accesați contul. Setați o parolă și încercați din nou."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Dispozitivul nu respectă politica de securitate stabilită de administrator."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vă conectați cu aplicația Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Pentru a vă proteja datele organizației, trebuie să vă conectați cu aplicația Device Policy înainte de a vă conecta."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Conectați"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ru.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ru.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..6d6c98ab --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/ru.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Войти"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Войти в аккаунт Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Надоело вводить пароль?"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Установите бесплатное приложение Google и входите в другие мобильные программы, используя учетные данные своего аккаунта."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Отмена"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Установить"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "ОК"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Отмена"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Настройки"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Не удалось войти в аккаунт"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "В соответствии с требованиями администратора для входа в аккаунт необходимо установить на устройстве код доступа. Сделайте это и повторите попытку."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Устройство не соответствует правилам безопасности, которые установлены администратором."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Подключить приложение Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "В целях защиты корпоративных данных перед входом в аккаунт необходимо подключить приложение Device Policy."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Подключить"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sk.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sk.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..eaf2f7f2 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sk.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Prihlásiť sa"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Prihlásiť sa pomocou účtu Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Prihlásenie pomocou účtu Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Nainštalujte si zdarma aplikáciu Google a prihlasujte sa do aplikácií pomocou účtu Google. Nebudete si už musieť pamätať rôzne heslá."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Zrušiť"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Inštalovať"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Zrušiť"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Nastavenia"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Nedá sa prihlásiť do účtu"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Správca vyžaduje, aby ste v tomto zariadení nastavili vstupný kód na prístup do príslušného účtu. Nastavte vstupný kód a skúste to znova."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Zariadenie nespĺňa pravidlá zabezpečenia nastavené vaším správcom."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Prepojiť s aplikáciou Pravidlá pre zariadenie?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Na to, aby bolo možné chrániť dáta vašej organizácie, je nutné pred prihlásením aktivovať prepojenie s aplikáciou Pravidlá pre zariadenie."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Prepojiť"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sv.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sv.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..3192e071 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/sv.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Logga in"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Logga in med Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Logga in med Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Hämta Google-appen utan kostnad och logga in i appar med ditt Google-konto. Du behöver inte komma ihåg en massa lösenord."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Avbryt"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Hämta"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "Ok"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Avbryt"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Inställningar"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Det gick inte att logga in på kontot"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Administratören kräver att du anger ett lösenord på den här enheten för att få åtkomst till kontot. Ange ett lösenord och försök igen."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Säkerhetspolicyn som administratören har angett efterlevs inte på enheten."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Vill du ansluta med appen Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Du måste ansluta med appen Device Policy innan du loggar in för att skydda organisationens data."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Anslut"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/th.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/th.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..353394ca --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/th.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "ลงชื่อเข้าใช้"; + +/* Long form sign-in button text */ +"Sign in with Google" = "ลงชื่อเข้าใช้ด้วย Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "ลงชื่อเข้าใช้ด้วย Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "ติดตั้งแอป Google ฟรีและลงชื่อเข้าใช้แอปต่างๆ ด้วยบัญชี Google คุณไม่ต้องจำรหัสผ่านอีกแล้ว"; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "ยกเลิก"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "ติดตั้ง"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "ตกลง"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "ยกเลิก"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "การตั้งค่า"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "ลงชื่อเข้าใช้บัญชีไม่ได้"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "ผู้ดูแลระบบกำหนดให้คุณตั้งรหัสผ่านในอุปกรณ์นี้เพื่อเข้าถึงบัญชีนี้ โปรดตั้งรหัสผ่าน แล้วลองอีกครั้ง"; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "อุปกรณ์ไม่ตรงตามนโยบายความปลอดภัยที่กำหนดโดยผู้ดูแลระบบของคุณ"; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "เชื่อมต่อแอป Device Policy ไหม"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "เพื่อปกป้องข้อมูลขององค์กร คุณต้องเชื่อมต่อแอป Device Policy ก่อนลงชื่อเข้าสู่ระบบ"; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "เชื่อมต่อ"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/tr.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/tr.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..414b7b9e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/tr.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Oturum aç"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Google ile oturum aç"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Google ile oturum aç"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Ücretsiz Google uygulamasını edinin ve uygulamalarda Google Hesabınızla oturum açın. Şifrelerinizi hatırlamanız gerekmez."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "İptal"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Yükle"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "Tamam"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "İptal"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Ayarlar"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Hesapta oturum açılamıyor"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Yöneticiniz, bu hesaba erişmek için bu cihazda bir şifre kodu ayarlamanızı gerektiriyor. Lütfen şifre kodu ayarlayın ve tekrar deneyin."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Bu cihaz, yöneticinizin ayarladığı güvenlik politikasıyla uyumlu değil."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Cihaz Politika Uygulamasına bağlanılsın mı?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Kuruluşunuzun verilerini korumak için, giriş yapmadan önce Cihaz Politikası uygulamasına bağlanmalısınız."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Bağlan"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/uk.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/uk.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..faaa0bc6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/uk.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Увійти"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Увійти в обліковий запис Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Входьте в обліковий запис Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Установіть безкоштовний додаток Google і входьте в обліковий запис Google у додатках. Не потрібно запам’ятовувати паролі."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Скасувати"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Установити"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Скасувати"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Налаштування"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Не вдається ввійти в обліковий запис"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Щоб увійти в обліковий запис, потрібно налаштувати код доступу на пристрої. Зробіть це й повторіть спробу."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Пристрій не відповідає правилу безпеки, яке налаштував адміністратор."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "З’єднатися з додатком Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Щоб захистити дані організації, потрібно з’єднатися з додатком Device Policy, перш ніж увійти."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "З’єднатися"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/vi.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/vi.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..94f858ce --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/vi.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "Đăng nhập"; + +/* Long form sign-in button text */ +"Sign in with Google" = "Đăng nhập bằng Google"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "Đăng nhập bằng Google"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "Tải ứng dụng Google miễn phí và đăng nhập vào các ứng dụng bằng Tài khoản Google của bạn. Không cần phải nhớ mật khẩu."; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "Hủy"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "Tải"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "OK"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "Hủy"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "Cài đặt"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "Không thể đăng nhập vào tài khoản"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "Quản trị viên của bạn yêu cầu bạn phải đặt mật mã trên thiết bị này để truy cập vào tài khoản này. Hãy đặt mật mã và thử lại."; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "Thiết bị này không tuân thủ chính sách bảo mật do quản trị viên của bạn thiết lập."; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "Kết nối với ứng dụng Device Policy?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "Để bảo vệ dữ liệu của tổ chức của mình, bạn phải kết nối với ứng dụng Device Policy trước khi đăng nhập."; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "Kết nối"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_CN.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_CN.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..0c087f61 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_CN.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "登录"; + +/* Long form sign-in button text */ +"Sign in with Google" = "使用 Google 帐号登录"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "使用 Google 帐号登录"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "安装免费的“Google”应用后,您可以使用自己的 Google 帐号登录众多应用(无需记住众多密码)。"; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "取消"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "安装"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "确定"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "取消"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "设置"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "无法登录帐号"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "您的管理员要求您必须先在此设备上设置密码,然后才能访问此帐号。请设置密码并重试。"; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "该设备不符合管理员设置的安全政策。"; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "要关联 Device Policy 应用吗?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "要保护您组织的数据,您必须在登录前关联 Device Policy 应用。"; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "关联"; diff --git a/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_TW.lproj/GoogleSignIn.strings b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_TW.lproj/GoogleSignIn.strings new file mode 100755 index 00000000..748468f1 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleSignIn/Resources/GoogleSignIn.bundle/zh_TW.lproj/GoogleSignIn.strings @@ -0,0 +1,44 @@ +/* Sign-in button text */ +"Sign in" = "登入"; + +/* Long form sign-in button text */ +"Sign in with Google" = "登入 Google 帳戶"; + +/* The title of the promotional prompt to install the Google app. */ +"PromoTitle" = "登入 Google 帳戶"; + +/* The body message of the promotional prompt to install the Google app. */ +"PromoMessage" = "只要安裝免費的 Google app,即可使用 Google 帳戶登入應用程式,而不必費心記住密碼。"; + +/* The cancel button on the promotional prompt to install the Google app. */ +"PromoActionCancel" = "取消"; + +/* The install button on the promotional prompt to install the Google app. */ +"PromoActionInstall" = "安裝"; + +/* The text for the button for user to acknowledge and dismiss a dialog. */ +"OK" = "確定"; + +/* The text for the button for user to dismiss a dialog without taking any action. */ +"Cancel" = "取消"; + +/* The name of the iOS native "Settings" app. */ +"SettingsAppName" = "設定"; + +/* The title for the error dialog for unable to sign in because of EMM policy. */ +"EmmErrorTitle" = "無法登入帳戶"; + +/* The text in the error dialog asking user to set up a passcode for the device due to EMM policy. */ +"EmmPasscodeRequired" = "管理員要求您必須為這個裝置設定通行碼,才能存取這個帳戶。請設定通行碼,然後再試一次。"; + +/* The text in the error dialog informing user that EMM policy prevented sign-in on the device. */ +"EmmGeneralError" = "這部裝置不符合您的管理員所設定的安全性政策規定。"; + +/* The title in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectTitle" = "要連結 Device Policy 應用程式嗎?"; + +/* The text in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectText" = "為了保護貴機構的資料,您必須在登入前連結 Device Policy 應用程式。"; + +/* The action button label in the error dialog informing user that connecting with Device Policy app is required. */ +"EmmConnectLabel" = "連結"; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m new file mode 100644 index 00000000..173a776d --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -0,0 +1,1038 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import +#import +#import +#import "GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h" +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +#import + +// Implementations need to be typed before calling the implementation directly to cast the +// arguments and the return types correctly. Otherwise, it will crash the app. +typedef BOOL (*GULRealOpenURLSourceApplicationAnnotationIMP)( + id, SEL, GULApplication *, NSURL *, NSString *, id); + +typedef BOOL (*GULRealOpenURLOptionsIMP)( + id, SEL, GULApplication *, NSURL *, NSDictionary *); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( + id, SEL, GULApplication *, NSString *, void (^)()); +#pragma clang diagnostic pop + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef BOOL (*GULRealContinueUserActivityIMP)( + id, SEL, GULApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); +#pragma clang diagnostic pop + +typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, GULApplication *, NSData *); + +typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, + SEL, + GULApplication *, + NSError *); + +typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, GULApplication *, NSDictionary *); + +// TODO: Since we don't support iOS 7 anymore, see if we can remove the check below. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( + id, SEL, GULApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +typedef void (^GULAppDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; + +static NSString *const kGULAppDelegateKeyPath = @"delegate"; + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/AppDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseAppDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the App Delegate. */ +static NSString *const kGULAppDelegatePrefix = @"GUL_"; + +/** The original instance of App Delegate. */ +static id gOriginalAppDelegate; + +/** The original App Delegate class */ +static Class gOriginalAppDelegateClass; + +/** The subclass of the original App Delegate. */ +static Class gAppDelegateSubclass; + +/** Remote notification methods selectors + * + * We have to opt out of referencing APNS related App Delegate methods directly to prevent + * an Apple review warning email about missing Push Notification Entitlement + * (like here: https://github.com/firebase/firebase-ios-sdk/issues/2807). From our experience, the + * warning is triggered when any of the symbols is present in the application sent to review, even + * if the code is never executed. Because GULAppDelegateSwizzler may be used by applications that + * are not using APNS we have to refer to the methods indirectly using selector constructed from + * string. + * + * NOTE: None of the methods is proxied unless it is explicitly requested by calling the method + * +[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods] + */ +static NSString *const kGULDidRegisterForRemoteNotificationsSEL = + @"application:didRegisterForRemoteNotificationsWithDeviceToken:"; +static NSString *const kGULDidFailToRegisterForRemoteNotificationsSEL = + @"application:didFailToRegisterForRemoteNotificationsWithError:"; +static NSString *const kGULDidReceiveRemoteNotificationSEL = + @"application:didReceiveRemoteNotification:"; +static NSString *const kGULDidReceiveRemoteNotificationWithCompletionSEL = + @"application:didReceiveRemoteNotification:fetchCompletionHandler:"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULZeroingWeakContainer +@end + +@interface GULAppDelegateObserver : NSObject +@end + +@implementation GULAppDelegateObserver { + BOOL _isObserving; +} + ++ (GULAppDelegateObserver *)sharedInstance { + static GULAppDelegateObserver *instance; + static dispatch_once_t once; + dispatch_once(&once, ^{ + instance = [[GULAppDelegateObserver alloc] init]; + }); + return instance; +} + +- (void)observeUIApplication { + if (_isObserving) { + return; + } + [[GULAppDelegateSwizzler sharedApplication] + addObserver:self + forKeyPath:kGULAppDelegateKeyPath + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:nil]; + _isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqual:kGULAppDelegateKeyPath]) { + id newValue = change[NSKeyValueChangeNewKey]; + id oldValue = change[NSKeyValueChangeOldKey]; + if ([newValue isEqual:oldValue]) { + return; + } + // Free the stored app delegate instance because it has been changed to a different instance to + // avoid keeping it alive forever. + if ([oldValue isEqual:gOriginalAppDelegate]) { + gOriginalAppDelegate = nil; + // Remove the observer. Parse it to NSObject to avoid warning. + [[GULAppDelegateSwizzler sharedApplication] removeObserver:self + forKeyPath:kGULAppDelegateKeyPath]; + _isObserving = NO; + } + } +} + +@end + +@implementation GULAppDelegateSwizzler + +static dispatch_once_t sProxyAppDelegateOnceToken; +static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; + +#pragma mark - Public methods + ++ (BOOL)isAppDelegateProxyEnabled { + NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; + + id isFirebaseProxyEnabledPlistValue = infoDictionary[kGULFirebaseAppDelegateProxyEnabledPlistKey]; + id isGoogleProxyEnabledPlistValue = + infoDictionary[kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey]; + + // Enabled by default. + BOOL isFirebaseAppDelegateProxyEnabled = YES; + BOOL isGoogleUtilitiesAppDelegateProxyEnabled = YES; + + if ([isFirebaseProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isFirebaseAppDelegateProxyEnabled = [isFirebaseProxyEnabledPlistValue boolValue]; + } + + if ([isGoogleProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isGoogleUtilitiesAppDelegateProxyEnabled = [isGoogleProxyEnabledPlistValue boolValue]; + } + + // Only deactivate the proxy if it is explicitly disabled by app developers using either one of + // the plist flags. + return isFirebaseAppDelegateProxyEnabled && isGoogleUtilitiesAppDelegateProxyEnabled; +} + ++ (GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor { + NSAssert(interceptor, @"AppDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(GULApplicationDelegate)], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling000], + @"AppDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling001], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = [NSString stringWithFormat:@"%@%p", kGULAppDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling002], + @"AppDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULZeroingWeakContainer *weakObject = [[GULZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULAppDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"AppDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"AppDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling003], + @"AppDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULZeroingWeakContainer *weakContainer = [GULAppDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling004], + @"AppDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + ++ (void)proxyOriginalDelegate { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + dispatch_once(&sProxyAppDelegateOnceToken, ^{ + id originalDelegate = + [GULAppDelegateSwizzler sharedApplication].delegate; + [GULAppDelegateSwizzler proxyAppDelegate:originalDelegate]; + }); +} + ++ (void)proxyOriginalDelegateIncludingAPNSMethods { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + [self proxyOriginalDelegate]; + + dispatch_once(&sProxyAppDelegateRemoteNotificationOnceToken, ^{ + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; + + NSMutableDictionary *realImplementationsBySelector = + [objc_getAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey) mutableCopy]; + + [self proxyRemoteNotificationsMethodsWithAppDelegateSubClass:gAppDelegateSubclass + realClass:gOriginalAppDelegateClass + appDelegate:appDelegate + realImplementationsBySelector:realImplementationsBySelector]; + + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN); + [self reassignAppDelegate]; + }); +} + +#pragma mark - Create proxy + ++ (GULApplication *)sharedApplication { + if ([GULAppEnvironmentUtil isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(kGULApplicationClassName); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - Override default methods + +/** Creates a new subclass of the class of the given object and sets the isa value of the given + * object to the new subclass. Additionally this copies methods to that new subclass that allow us + * to intercept UIApplicationDelegate methods. This is better known as isa swizzling. + * + * @param appDelegate The object to which you want to isa swizzle. This has to conform to the + * UIApplicationDelegate subclass. + * @return Returns the new subclass. + */ ++ (nullable Class)createSubclassWithObject:(id)appDelegate { + Class realClass = [appDelegate class]; + + // Create GUL__ + NSString *classNameWithPrefix = + [kGULAppDelegatePrefix stringByAppendingString:NSStringFromClass(realClass)]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling005], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: %@", + NSStringFromClass(realClass), newClassName); + return nil; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class appDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (appDelegateSubClass == Nil) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling006], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: Nil", + NSStringFromClass(realClass)); + return nil; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For application:continueUserActivity:restorationHandler: + SEL continueUserActivitySEL = @selector(application:continueUserActivity:restorationHandler:); + [self proxyDestinationSelector:continueUserActivitySEL + implementationsFromSourceSelector:continueUserActivitySEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + +#if TARGET_OS_IOS || TARGET_OS_TV + // Add the following methods from GULAppDelegate class, and store the real implementation so it + // can forward to the real one. + // For application:openURL:options: + SEL applicationOpenURLOptionsSEL = @selector(application:openURL:options:); + if ([appDelegate respondsToSelector:applicationOpenURLOptionsSEL]) { + // Only add the application:openURL:options: method if the original AppDelegate implements it. + // This fixes a bug if an app only implements application:openURL:sourceApplication:annotation: + // (if we add the `options` method, iOS sees that one exists and does not call the + // `sourceApplication` method, which in this case is the only one the app implements). + + [self proxyDestinationSelector:applicationOpenURLOptionsSEL + implementationsFromSourceSelector:applicationOpenURLOptionsSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + + // For application:handleEventsForBackgroundURLSession:completionHandler: + SEL handleEventsForBackgroundURLSessionSEL = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + [self proxyDestinationSelector:handleEventsForBackgroundURLSessionSEL + implementationsFromSourceSelector:handleEventsForBackgroundURLSessionSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + // For application:openURL:sourceApplication:annotation: + SEL openURLSourceApplicationAnnotationSEL = @selector(application: + openURL:sourceApplication:annotation:); + + [self proxyDestinationSelector:openURLSourceApplicationAnnotationSEL + implementationsFromSourceSelector:openURLSourceApplicationAnnotationSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS + + // Override the description too so the custom class name will not show up. + [GULAppDelegateSwizzler addInstanceMethodWithDestinationSelector:@selector(description) + withImplementationFromSourceSelector:@selector(fakeDescription) + fromClass:[self class] + toClass:appDelegateSubClass]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(appDelegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(appDelegateSubClass)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling007], + @"Cannot create subclass of App Delegate, because the created subclass is not the " + @"same size. %@", + NSStringFromClass(realClass)); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return nil; + } + + // Make the newly created class to be the subclass of the real App Delegate class. + objc_registerClassPair(appDelegateSubClass); + if (object_setClass(appDelegate, appDelegateSubClass)) { + GULLogDebug(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling008], + @"Successfully created App Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULAppDelegateSwizzler correctAppDelegateProxyKey]); + } + + return appDelegateSubClass; +} + ++ (void)proxyRemoteNotificationsMethodsWithAppDelegateSubClass:(Class)appDelegateSubClass + realClass:(Class)realClass + appDelegate:(id)appDelegate + realImplementationsBySelector: + (NSMutableDictionary *)realImplementationsBySelector { + if (realClass == nil || appDelegateSubClass == nil || appDelegate == nil || + realImplementationsBySelector == nil) { + // The App Delegate has not been swizzled. + return; + } + + // For application:didRegisterForRemoteNotificationsWithDeviceToken: + SEL didRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + SEL didRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didRegisterForRemoteNotificationsWithDeviceToken:); + + [self proxyDestinationSelector:didRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didFailToRegisterForRemoteNotificationsWithError: + SEL didFailToRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + SEL didFailToRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didFailToRegisterForRemoteNotificationsWithError:); + + [self proxyDestinationSelector:didFailToRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didFailToRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification: + SEL didReceiveRemoteNotificationSEL = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + SEL didReceiveRemoteNotificationDonotSEL = @selector(application: + donor_didReceiveRemoteNotification:); + + [self proxyDestinationSelector:didReceiveRemoteNotificationSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationDonotSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification:fetchCompletionHandler: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + if ([GULAppEnvironmentUtil isIOS7OrHigher]) { + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). + + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + } +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +} + +/// We have to do this to invalidate the cache that caches the original respondsToSelector of +/// openURL handlers. Without this, it won't call the default implementations because the system +/// checks and caches them. +/// Register KVO only once. Otherwise, the observing method will be called as many times as +/// being registered. ++ (void)reassignAppDelegate { +#if !TARGET_OS_WATCH + id delegate = [self sharedApplication].delegate; + [self sharedApplication].delegate = nil; + [self sharedApplication].delegate = delegate; + gOriginalAppDelegate = delegate; + [[GULAppDelegateObserver sharedInstance] observeUIApplication]; +#endif +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULAppDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULAppDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULAppDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULAppDelegateInterceptorCallback)callback { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULAppDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeAppDelegateSwizzling010], + @"AppDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + +// The methods below are donor methods which are added to the dynamic subclass of the App Delegate. +// They are called within the scope of the real App Delegate so |self| does not refer to the +// GULAppDelegateSwizzler instance but the real App Delegate instance. + +#pragma mark - [Donor Methods] Overridden instance description method + +- (NSString *)fakeDescription { + Class realClass = objc_getAssociatedObject(self, &kGULRealClassKey); + return [NSString stringWithFormat:@"<%@: %p>", realClass, self]; +} + +#pragma mark - [Donor Methods] URL overridden handler methods +#if TARGET_OS_IOS || TARGET_OS_TV + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options { + SEL methodSelector = @selector(application:openURL:options:); + // Call the real implementation if the real App Delegate has any. + NSValue *openURLIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLOptionsIMP openURLOptionsIMP = [openURLIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + +// This is needed to for the library to be warning free on iOS versions < 9. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + openURL:url + options:options]; + }]; +#pragma clang diagnostic pop + if (openURLOptionsIMP) { + returnedValue |= openURLOptionsIMP(self, methodSelector, application, url, options); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { + SEL methodSelector = @selector(application:openURL:sourceApplication:annotation:); + + // Call the real implementation if the real App Delegate has any. + NSValue *openURLSourceAppAnnotationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLSourceApplicationAnnotationIMP openURLSourceApplicationAnnotationIMP = + [openURLSourceAppAnnotationIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + returnedValue |= [interceptor application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#pragma clang diagnostic pop + }]; + if (openURLSourceApplicationAnnotationIMP) { + returnedValue |= openURLSourceApplicationAnnotationIMP(self, methodSelector, application, url, + sourceApplication, annotation); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS + +#pragma mark - [Donor Methods] Network overridden handler methods + +#if TARGET_OS_IOS || TARGET_OS_TV + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +- (void)application:(GULApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(void (^)())completionHandler API_AVAILABLE(ios(7.0)) { +#pragma clang diagnostic pop + SEL methodSelector = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + NSValue *handleBackgroundSessionPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealHandleEventsForBackgroundURLSessionIMP handleBackgroundSessionIMP = + [handleBackgroundSessionPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + [interceptor application:application + handleEventsForBackgroundURLSession:identifier + completionHandler:completionHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (handleBackgroundSessionIMP) { + handleBackgroundSessionIMP(self, methodSelector, application, identifier, completionHandler); + } +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - [Donor Methods] User Activities overridden handler methods + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (BOOL)application:(GULApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + SEL methodSelector = @selector(application:continueUserActivity:restorationHandler:); + NSValue *continueUserActivityIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealContinueUserActivityIMP continueUserActivityIMP = + continueUserActivityIMPPointer.pointerValue; + + __block BOOL returnedValue = NO; +#if !TARGET_OS_WATCH + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; + }]; +#endif + // Call the real implementation if the real App Delegate has any. + if (continueUserActivityIMP) { + returnedValue |= continueUserActivityIMP(self, methodSelector, application, userActivity, + restorationHandler); + } + return returnedValue; +} +#pragma clang diagnostic pop + +#pragma mark - [Donor Methods] Remote Notifications + +- (void)application:(GULApplication *)application + donor_didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + SEL methodSelector = NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + + NSValue *didRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidRegisterForRemoteNotificationsIMP didRegisterForRemoteNotificationsIMP = + [didRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&deviceToken) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didRegisterForRemoteNotificationsIMP) { + didRegisterForRemoteNotificationsIMP(self, methodSelector, application, deviceToken); + } +} + +- (void)application:(GULApplication *)application + donor_didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + SEL methodSelector = NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + NSValue *didFailToRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidFailToRegisterForRemoteNotificationsIMP didFailToRegisterForRemoteNotificationsIMP = + [didFailToRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&error) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didFailToRegisterForRemoteNotificationsIMP) { + didFailToRegisterForRemoteNotificationsIMP(self, methodSelector, application, error); + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + NSValue *didReceiveRemoteNotificationWithCompletionIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationWithCompletionIMP + didReceiveRemoteNotificationWithCompletionIMP = + [didReceiveRemoteNotificationWithCompletionIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation setArgument:(void *)(&completionHandler) atIndex:4]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationWithCompletionIMP) { + didReceiveRemoteNotificationWithCompletionIMP(self, methodSelector, application, userInfo, + completionHandler); + } +} +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + NSValue *didReceiveRemoteNotificationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationIMP didReceiveRemoteNotificationIMP = + [didReceiveRemoteNotificationIMPPointer pointerValue]; + + // Notify interceptors. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation invoke]; + }]; +#pragma clang diagnostic pop + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationIMP) { + didReceiveRemoteNotificationIMP(self, methodSelector, application, userInfo); + } +} + ++ (nullable NSInvocation *)appDelegateInvocationForSelector:(SEL)selector { + struct objc_method_description methodDescription = + protocol_getMethodDescription(@protocol(GULApplicationDelegate), selector, NO, YES); + if (methodDescription.types == NULL) { + return nil; + } + + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSInvocation invocationWithMethodSignature:signature]; +} + ++ (void)proxyAppDelegate:(id)appDelegate { + if (![appDelegate conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogNotice( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate], + @"App Delegate does not conform to UIApplicationDelegate protocol. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + id originalDelegate = appDelegate; + // Do not create a subclass if it is not enabled. + if (![GULAppDelegateSwizzler isAppDelegateProxyEnabled]) { + GULLogNotice(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling011], + @"App Delegate Proxy is disabled. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + // Do not accept nil delegate. + if (!originalDelegate) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling012], + @"Cannot create App Delegate Proxy because App Delegate instance is nil. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + @try { + gOriginalAppDelegateClass = [originalDelegate class]; + gAppDelegateSubclass = [self createSubclassWithObject:originalDelegate]; + [self reassignAppDelegate]; + } @catch (NSException *exception) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling013], + @"Cannot create App Delegate Proxy. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } +} + +#pragma mark - Methods to print correct debug logs + ++ (NSString *)correctAppDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseAppDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey; +} + ++ (NSString *)correctAlternativeWhenAppDelegateProxyNotCreated { + return NSClassFromString(@"FIRCore") + ? @"To log deep link campaigns manually, call the methods in " + @"FIRAnalytics+AppDelegate.h." + : @""; +} + +#pragma mark - Private Methods for Testing + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (void)resetProxyOriginalDelegateOnceToken { + sProxyAppDelegateOnceToken = 0; + sProxyAppDelegateRemoteNotificationOnceToken = 0; +} + ++ (id)originalDelegate { + return gOriginalAppDelegate; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h new file mode 100644 index 00000000..d7ebd868 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -0,0 +1,55 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +@class GULApplication; + +NS_ASSUME_NONNULL_BEGIN + +@interface GULAppDelegateSwizzler () + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param appDelegate The object that needs to be isa swizzled. This should conform to the + * application delegate protocol. + */ ++ (void)proxyAppDelegate:(id)appDelegate; + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */ ++ (void)resetProxyOriginalDelegateOnceToken; + +/** Returns the original app delegate that was proxied. + * + * @return The original app delegate instance that was proxied. + */ ++ (id)originalDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h new file mode 100644 index 00000000..c1b2d6e1 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULAppDelegateInterceptorID; + +/** This class contains methods that isa swizzle the app delegate. */ +@interface GULAppDelegateSwizzler : NSProxy + +/** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the + * original app delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor; + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID; + +/** This method ensures that the original app delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the app delegate once). + * + * This method doesn't proxy APNS related methods: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * To proxy these methods use +[GULAppDelegateSwizzler + * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to + * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g. + * https://github.com/firebase/firebase-ios-sdk/issues/2807) + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegateIncludingAPNSMethods + */ ++ (void)proxyOriginalDelegate; + +/** This method ensures that the original app delegate has been proxied including APNS related + * methods. Call this before registering your interceptor. This method is safe to call multiple + * times (but it only proxies the app delegate once) or + * after +[GULAppDelegateSwizzler proxyOriginalDelegate] + * + * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood. + * After calling this method the following App Delegate methods will be proxied in addition to + * the methods proxied by proxyOriginalDelegate: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegate + */ ++ (void)proxyOriginalDelegateIncludingAPNSMethods; + +/** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if AppDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isAppDelegateProxyEnabled; + +/** Returns the current sharedApplication. + * + * @return the current application instance if in an app, or nil if in extension or if it doesn't + * exist. + */ ++ (nullable GULApplication *)sharedApplication; + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +NS_ASSUME_NONNULL_END + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h new file mode 100644 index 00000000..80672124 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_TV + +#import + +#define GULApplication UIApplication +#define GULApplicationDelegate UIApplicationDelegate +#define GULUserActivityRestoring UIUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"UIApplication"; + +#elif TARGET_OS_OSX + +#import + +#define GULApplication NSApplication +#define GULApplicationDelegate NSApplicationDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"NSApplication"; + +#elif TARGET_OS_WATCH + +#import + +// We match the according watchOS API but swizzling should not work in watch +#define GULApplication WKExtension +#define GULApplicationDelegate WKExtensionDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"WKExtension"; + +#endif diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h new file mode 100644 index 00000000..053ce843 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) { + // App Delegate Swizzling. + kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000 + kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001 + kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002 + kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003 + kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004 + kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005 + kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006 + kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007 + kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008 + kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009 + kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010 + kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011 + kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012 + kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013 + kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014 + + // Scene Delegate Swizzling. + kGULSwizzlerMessageCodeSceneDelegateSwizzling000 = 1100, // I-SWZ001100 + kGULSwizzlerMessageCodeSceneDelegateSwizzling001 = 1101, // I-SWZ001101 + kGULSwizzlerMessageCodeSceneDelegateSwizzling002 = 1102, // I-SWZ001102 + kGULSwizzlerMessageCodeSceneDelegateSwizzling003 = 1103, // I-SWZ001103 + kGULSwizzlerMessageCodeSceneDelegateSwizzling004 = 1104, // I-SWZ001104 + kGULSwizzlerMessageCodeSceneDelegateSwizzling005 = 1105, // I-SWZ001105 + kGULSwizzlerMessageCodeSceneDelegateSwizzling006 = 1106, // I-SWZ001106 + kGULSwizzlerMessageCodeSceneDelegateSwizzling007 = 1107, // I-SWZ001107 + kGULSwizzlerMessageCodeSceneDelegateSwizzling008 = 1108, // I-SWZ001108 + kGULSwizzlerMessageCodeSceneDelegateSwizzling009 = 1109, // I-SWZ001109 + kGULSwizzlerMessageCodeSceneDelegateSwizzling010 = 1110, // I-SWZ001110 + kGULSwizzlerMessageCodeSceneDelegateSwizzling011 = 1111, // I-SWZ001111 + kGULSwizzlerMessageCodeSceneDelegateSwizzling012 = 1112, // I-SWZ001112 + kGULSwizzlerMessageCodeSceneDelegateSwizzling013 = 1113, // I-SWZ001113 + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate = 1114, // I-SWZ001114 + + // Method Swizzling. + kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000 +}; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m new file mode 100644 index 00000000..483c8590 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m @@ -0,0 +1,140 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@interface GULHeartbeatDateStorage () +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) NSFileCoordinator *fileCoordinator; +@end + +@implementation GULHeartbeatDateStorage + +- (instancetype)initWithFileName:(NSString *)fileName { + if (fileName == nil) { + return nil; + } + + self = [super init]; + if (self) { + _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *directoryURL = [[self class] directoryPathURL]; + [[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator]; + _fileURL = [directoryURL URLByAppendingPathComponent:fileName]; + } + return self; +} + +/** Returns the URL path of the Application Support folder. + * @return the URL path of Application Support. + */ ++ (NSURL *)directoryPathURL { + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSArray *components = @[ paths.lastObject, @"Google/FIRApp" ]; + NSString *directoryString = [NSString pathWithComponents:components]; + NSURL *directoryURL = [NSURL fileURLWithPath:directoryString]; + return directoryURL; +} + +/** Checks and creates a directory for the directory specified by the + * directory url + * @param directoryPathURL The path to the directory which needs to be created. + * @param fileCoordinator The fileCoordinator object to coordinate writes to the directory. + */ ++ (void)checkAndCreateDirectory:(NSURL *)directoryPathURL + fileCoordinator:(NSFileCoordinator *)fileCoordinator { + NSError *fileCoordinatorError = nil; + [fileCoordinator + coordinateWritingItemAtURL:directoryPathURL + options:0 + error:&fileCoordinatorError + byAccessor:^(NSURL *writingDirectoryURL) { + NSError *error; + if (![writingDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + // If fail creating the Application Support directory, log warning. + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtURL:writingDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&error]; + } + }]; +} + +- (nullable NSMutableDictionary *)heartbeatDictionaryWithFileURL:(NSURL *)readingFileURL { + NSError *error; + NSMutableDictionary *dict; + NSData *objectData = [NSData dataWithContentsOfURL:readingFileURL options:0 error:&error]; + if (objectData == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } else { + dict = [GULSecureCoding + unarchivedObjectOfClasses:[NSSet setWithArray:@[ NSDictionary.class, NSDate.class ]] + fromData:objectData + error:&error]; + if (dict == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } + } + return dict; +} + +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag { + __block NSMutableDictionary *dict; + NSError *error; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL) { + dict = [self heartbeatDictionaryWithFileURL:readingURL]; + }]; + return dict[tag]; +} + +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag { + NSError *error; + __block BOOL isSuccess = false; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + writingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL, NSURL *writingURL) { + NSMutableDictionary *dictionary = + [self heartbeatDictionaryWithFileURL:readingURL]; + dictionary[tag] = date; + NSError *error; + isSuccess = [self writeDictionary:dictionary + forWritingURL:writingURL + error:&error]; + }]; + return isSuccess; +} + +- (BOOL)writeDictionary:(NSMutableDictionary *)dictionary + forWritingURL:(NSURL *)writingFileURL + error:(NSError **)outError { + NSData *data = [GULSecureCoding archivedDataWithRootObject:dictionary error:outError]; + if (*outError != nil) { + return false; + } else { + return [data writeToURL:writingFileURL atomically:YES]; + } +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m new file mode 100644 index 00000000..25d5d199 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m @@ -0,0 +1,103 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/Public/GULSecureCoding.h" + +NSString *const kGULSecureCodingError = @"GULSecureCodingError"; + +@implementation GULSecureCoding + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError { + id object; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) { + object = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:data error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + unarchiver.requiresSecureCoding = YES; + + object = [unarchiver decodeObjectOfClasses:classes forKey:NSKeyedArchiveRootObjectKey]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + + if (object == nil && outError && *outError == nil) { + NSString *failureReason = @"NSKeyedUnarchiver failed to unarchive data."; + *outError = [NSError errorWithDomain:kGULSecureCodingError + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : failureReason}]; + } + } + + return object; +} + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError { + return [self unarchivedObjectOfClasses:[NSSet setWithObject:class] fromData:data error:outError]; +} + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError { + NSData *archiveData; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) { + archiveData = [NSKeyedArchiver archivedDataWithRootObject:object + requiringSecureCoding:YES + error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { + NSMutableData *data = [NSMutableData data]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + archiver.requiresSecureCoding = YES; + + [archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey]; + [archiver finishEncoding]; + + archiveData = [data copy]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + } + + return archiveData; +} + ++ (NSError *)archivingErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + NSDictionary *errorUserInfo = @{NSLocalizedFailureReasonErrorKey : failureReason}; + + return [NSError errorWithDomain:kGULSecureCodingError code:-1 userInfo:errorUserInfo]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h new file mode 100644 index 00000000..9432dfc0 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Stores either a date or a dictionary to a specified file. +@interface GULHeartbeatDateStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, readonly) NSURL *fileURL; + +/** + * Default initializer. + * @param fileName The name of the file to store the date information. + * exist, it will be created if needed. + */ +- (instancetype)initWithFileName:(NSString *)fileName; + +/** + * Reads the date from the specified file for the given tag. + * @return Returns date if exists, otherwise `nil`. + */ +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag; + +/** + * Saves the date for the specified tag in the specified file. + * @return YES on success, NO otherwise. + */ +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h new file mode 100644 index 00000000..dc01a836 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainStorage.h @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/// The class provides a convenient abstraction on top of the iOS Keychain API to save data. +@interface GULKeychainStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes the keychain storage with Keychain Service name. + * @param service A Keychain Service name that will be used to store and retrieve objects. See also + * `kSecAttrService`. + */ +- (instancetype)initWithService:(NSString *)service; + +/** + * Get an object by key. + * @param key The key. + * @param objectClass The expected object class required by `NSSecureCoding`. + * @param accessGroup The Keychain Access Group. + * + * @return Returns a promise. It is resolved with an object stored by key if exists. It is resolved + * with `nil` when the object not found. It fails on a Keychain error. + */ +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup; + +/** + * Saves the given object by the given key. + * @param object The object to store. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +/** + * Removes the object by the given key. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h new file mode 100644 index 00000000..de4bef2f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULKeychainUtils.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kGULKeychainUtilsErrorDomain; + +/// Helper functions to access Keychain. +@interface GULKeychainUtils : NSObject + +/** Fetches a keychain item data matching to the provided query. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemCopyMatching` for + * details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns Data for the first Keychain Item matching the provided query or `nil` if there is not + * such an item (`outError` will be `nil` in this case) or an error occurred. + */ ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** Stores data to a Keychain Item matching to the provided query. An existing Keychain Item + * matching the query parameters will be updated or a new will be created. + * @param item A Keychain Item data to store. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemAdd` and + * `SecItemUpdate` for details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns `YES` when data was successfully stored, `NO` otherwise. + */ ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + +/** Removes a Keychain Item matching to the provided query. + * @param query A dictionary with Keychain query parameters. See docs for `SecItemDelete` for + * details. + * @param outError A pointer to `NSError` instance or `NULL`. The instance at `outError` will be + * assigned with an error if there is. + * @returns `YES` if the item was removed successfully or doesn't exist, `NO` otherwise. + */ ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h new file mode 100644 index 00000000..8484b395 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class wraps `NSKeyedArchiver` and `NSKeyedUnarchiver` API to provide a unified secure coding + * methods for iOS versions before and after 11. + */ +@interface GULSecureCoding : NSObject + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m new file mode 100644 index 00000000..3777724b --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m @@ -0,0 +1,192 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import + +@interface GULKeychainStorage () +@property(nonatomic, readonly) dispatch_queue_t keychainQueue; +@property(nonatomic, readonly) dispatch_queue_t inMemoryCacheQueue; +@property(nonatomic, readonly) NSString *service; +@property(nonatomic, readonly) NSCache> *inMemoryCache; +@end + +@implementation GULKeychainStorage + +- (instancetype)initWithService:(NSString *)service { + NSCache *cache = [[NSCache alloc] init]; + // Cache up to 5 installations. + cache.countLimit = 5; + return [self initWithService:service cache:cache]; +} + +- (instancetype)initWithService:(NSString *)service cache:(NSCache *)cache { + self = [super init]; + if (self) { + _keychainQueue = + dispatch_queue_create("com.gul.KeychainStorage.Keychain", DISPATCH_QUEUE_SERIAL); + _inMemoryCacheQueue = + dispatch_queue_create("com.gul.KeychainStorage.InMemoryCache", DISPATCH_QUEUE_SERIAL); + _service = [service copy]; + _inMemoryCache = cache; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Return cached object or fail otherwise. + id object = [self.inMemoryCache objectForKey:key]; + return object + ?: [[NSError alloc] + initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }] + .recover(^id _Nullable(NSError *error) { + // Look for the object in the keychain. + return [self getObjectFromKeychainForKey:key + objectClass:objectClass + accessGroup:accessGroup]; + }); +} + +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Save to the in-memory cache first. + [self.inMemoryCache setObject:object forKey:[key copy]]; + return [NSNull null]; + }] + .thenOn(self.keychainQueue, ^id(id result) { + // Then store the object to the keychain. + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = [GULSecureCoding archivedDataWithRootObject:object error:&error]; + if (!encodedObject) { + return error; + } + + if (![GULKeychainUtils setItem:encodedObject withQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + [self.inMemoryCache removeObjectForKey:key]; + return nil; + }] + .thenOn(self.keychainQueue, ^id(id result) { + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + + NSError *error; + if (![GULKeychainUtils removeItemWithQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +#pragma mark - Private + +- (FBLPromise> *)getObjectFromKeychainForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + // Look for the object in the keychain. + return [FBLPromise + onQueue:self.keychainQueue + do:^id { + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = [GULKeychainUtils getItemWithQuery:query error:&error]; + + if (error) { + return error; + } + if (!encodedObject) { + return nil; + } + id object = [GULSecureCoding unarchivedObjectOfClass:objectClass + fromData:encodedObject + error:&error]; + if (error) { + return error; + } + + return object; + }] + .thenOn(self.inMemoryCacheQueue, + ^id _Nullable(id _Nullable object) { + // Save object to the in-memory cache if exists and return the object. + if (object) { + [self.inMemoryCache setObject:object forKey:[key copy]]; + } + return object; + }); +} + +- (void)resetInMemoryCache { + [self.inMemoryCache removeAllObjects]; +} + +#pragma mark - Keychain + +- (NSMutableDictionary *)keychainQueryWithKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + + query[(__bridge NSString *)kSecClass] = (__bridge NSString *)kSecClassGenericPassword; + query[(__bridge NSString *)kSecAttrService] = self.service; + query[(__bridge NSString *)kSecAttrAccount] = key; + + if (accessGroup) { + query[(__bridge NSString *)kSecAttrAccessGroup] = accessGroup; + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecUseKeychain] = (__bridge id)(self.keychainRef); + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m new file mode 100644 index 00000000..673b6c4f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m @@ -0,0 +1,113 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NSString *const kGULKeychainUtilsErrorDomain = @"com.gul.keychain.ErrorDomain"; + +@implementation GULKeychainUtils + ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *mutableQuery = [query mutableCopy]; + + mutableQuery[(__bridge id)kSecReturnData] = @YES; + mutableQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFDataRef result = NULL; + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)mutableQuery, (CFTypeRef *)&result); + + if (status == errSecSuccess && result != NULL) { + if (outError) { + *outError = nil; + } + + return (__bridge_transfer NSData *)result; + } + + if (status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + } else { + if (outError) { + *outError = [self keychainErrorWithFunction:@"SecItemCopyMatching" status:status]; + } + } + return nil; +} + ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSData *existingItem = [self getItemWithQuery:query error:outError]; + if (outError && *outError) { + return NO; + } + + NSMutableDictionary *mutableQuery = [query mutableCopy]; + mutableQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status; + if (!existingItem) { + mutableQuery[(__bridge id)kSecValueData] = item; + status = SecItemAdd((__bridge CFDictionaryRef)mutableQuery, NULL); + } else { + NSDictionary *attributes = @{(__bridge id)kSecValueData : item}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + + if (status == noErr) { + if (outError) { + *outError = nil; + } + return YES; + } + + NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd"; + if (outError) { + *outError = [self keychainErrorWithFunction:function status:status]; + } + return NO; +} + ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + + if (status == noErr || status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + return YES; + } + + if (outError) { + *outError = [self keychainErrorWithFunction:@"SecItemDelete" status:status]; + } + return NO; +} + +#pragma mark - Errors + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status { + NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status]; + NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey : failureReason}; + return [NSError errorWithDomain:kGULKeychainUtilsErrorDomain code:0 userInfo:userInfo]; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h new file mode 100644 index 00000000..d5502647 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m new file mode 100644 index 00000000..8b1ac6ab --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -0,0 +1,267 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h" + +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import +#endif + +/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from +/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just +/// provide the definitions here. +#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) +#define LC_ENCRYPTION_INFO 0x21 +struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; +}; +#endif + +@implementation GULAppEnvironmentUtil + +/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. +/// This will affect your data integrity when using Firebase Analytics, as it will disable some +/// necessary checks. +static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = + @"FirebaseAppStoreReceiptURLCheckEnabled"; + +/// The file name of the sandbox receipt. This is available on iOS >= 8.0 +static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; + +/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. +/// +/// Copyright (c) 2017 Landon J. Fuller +/// All rights reserved. +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +/// and associated documentation files (the "Software"), to deal in the Software without +/// restriction, including without limitation the rights to use, copy, modify, merge, publish, +/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +/// Software is furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in all copies or +/// substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/// +/// Comment from iPhone Dev Wiki +/// Crack Prevention: +/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so +/// that decryption keys are needed in order to make the binary readable. When iOS executes the +/// binary, the decryption keys are used to decrypt the binary into a readable state where it is +/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the +/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero +/// value then the binary is encrypted. +/// +/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into +/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as +/// codesignature validation has been removed. Resigning takes place because while the codesignature +/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have +/// AppSync or similar to disable codesignature checks. +/// +/// More information at Landon Fuller's blog +static BOOL IsAppEncrypted() { + const struct mach_header *executableHeader = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *header = _dyld_get_image_header(i); + if (header && header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + + if (!executableHeader) { + return NO; + } + + BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); + uintptr_t cursor = (uintptr_t)executableHeader + + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); + const struct segment_command *segmentCommand = NULL; + uint32_t i = 0; + + while (i++ < executableHeader->ncmds) { + segmentCommand = (struct segment_command *)cursor; + + if (!segmentCommand) { + continue; + } + + if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || + (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { + if (is64bit) { + struct encryption_info_command_64 *cryptCmd = + (struct encryption_info_command_64 *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } else { + struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } + } + cursor += segmentCommand->cmdsize; + } + + return NO; +} + +static BOOL HasSCInfoFolder() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *bundlePath = [NSBundle mainBundle].bundlePath; + NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; + return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; +#elif TARGET_OS_OSX + return NO; +#endif +} + +static BOOL HasEmbeddedMobileProvision() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isFromAppStore { + static dispatch_once_t isEncryptedOnce; + static BOOL isEncrypted = NO; + + dispatch_once(&isEncryptedOnce, ^{ + isEncrypted = IsAppEncrypted(); + }); + + if ([GULAppEnvironmentUtil isSimulator]) { + return NO; + } + + // If an app contain the sandboxReceipt file, it means its coming from TestFlight + // This must be checked before the SCInfo Folder check below since TestFlight apps may + // also have an SCInfo folder. + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { + return NO; + } + + if (HasSCInfoFolder()) { + // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the + // main SC_Info directory. + return YES; + } + + // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read + // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. + // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when + // the app is submitted to store, then it is highly likely that it is from Apple Store. + return isEncrypted && !HasEmbeddedMobileProvision(); +} + ++ (BOOL)isAppStoreReceiptSandbox { + // Since checking the App Store's receipt URL can be memory intensive, check the option in the + // Info.plist if developers opted out of this check. + id enableSandboxCheck = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; + if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && + ![enableSandboxCheck boolValue]) { + return NO; + } +// The #else is for pre Xcode 9 where @available is not yet implemented. +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; + } + return NO; +} + ++ (BOOL)isSimulator { +#if TARGET_OS_SIMULATOR + return YES; +#elif TARGET_OS_MACCATALYST + return NO; +#elif TARGET_OS_IOS || TARGET_OS_TV + NSString *platform = [GULAppEnvironmentUtil deviceModel]; + return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; +#elif TARGET_OS_OSX + return NO; +#endif + return NO; +} + ++ (NSString *)deviceModel { + static dispatch_once_t once; + static NSString *deviceModel; + + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return deviceModel; +} + ++ (NSString *)systemVersion { +#if TARGET_OS_IOS + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_TV || TARGET_OS_WATCH + // Assemble the systemVersion, excluding the patch version if it's 0. + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + NSMutableString *versionString = [[NSMutableString alloc] + initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; + if (osVersion.patchVersion != 0) { + [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; + } + return versionString; +#endif +} + ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + // Documented by Apple + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isIOS7OrHigher { +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + return YES; + } + + return NO; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/LICENSE b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/LICENSE new file mode 100644 index 00000000..30a8f725 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/LICENSE @@ -0,0 +1,247 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m new file mode 100644 index 00000000..0a512da6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -0,0 +1,214 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Logger/Private/GULLogger.h" + +#include + +#import +#import + +/// ASL client facility name used by GULLogger. +const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; + +static dispatch_once_t sGULLoggerOnceToken; + +static aslclient sGULLoggerClient; + +static dispatch_queue_t sGULClientQueue; + +static BOOL sGULLoggerDebugMode; + +static GULLoggerLevel sGULLoggerMaximumLevel; + +// Allow clients to register a version to include in the log. +static const char *sVersion = ""; + +static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void GULLoggerInitializeASL(void) { + dispatch_once(&sGULLoggerOnceToken, ^{ + NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; + uint32_t aslOptions = ASL_OPT_STDERR; +#if TARGET_OS_SIMULATOR + // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 11) { + aslOptions = 0; + } +#else + // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 10) { + aslOptions = 0; + } +#endif // TARGET_OS_SIMULATOR + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated + // Initialize the ASL client handle. + sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); + sGULLoggerMaximumLevel = GULLoggerLevelNotice; + + // Set the filter used by system/device log. Initialize in default mode. + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); + + sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(sGULClientQueue, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); +#ifdef DEBUG + sMessageCodeRegex = [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern + options:0 + error:NULL]; +#endif + }); +} + +void GULLoggerEnableSTDERR(void) { + asl_add_log_file(sGULLoggerClient, STDERR_FILENO); +} + +void GULLoggerForceDebug(void) { + // We should enable debug mode if we're not running from App Store. + if (![GULAppEnvironmentUtil isFromAppStore]) { + sGULLoggerDebugMode = YES; + GULSetLoggerLevel(GULLoggerLevelDebug); + } +} + +__attribute__((no_sanitize("thread"))) void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { + if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { + GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", + (long)loggerLevel); + return; + } + GULLoggerInitializeASL(); + // We should not raise the logger level if we are running from App Store. + if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { + return; + } + + sGULLoggerMaximumLevel = loggerLevel; + dispatch_async(sGULClientQueue, ^{ + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); + }); +} + +/** + * Check if the level is high enough to be loggable. + */ +__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { + GULLoggerInitializeASL(); + if (sGULLoggerDebugMode) { + return YES; + } + return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); +} + +#ifdef DEBUG +void GULResetLogger() { + sGULLoggerOnceToken = 0; +} + +aslclient getGULLoggerClient() { + return sGULLoggerClient; +} + +dispatch_queue_t getGULClientQueue() { + return sGULClientQueue; +} + +BOOL getGULLoggerDebugMode() { + return sGULLoggerDebugMode; +} +#endif + +void GULLoggerRegisterVersion(const char *version) { + sVersion = version; +} + +void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + GULLoggerInitializeASL(); + if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { + return; + } + +#ifdef DEBUG + NSCAssert(messageCode.length == 11, @"Incorrect message code length."); + NSRange messageCodeRange = NSMakeRange(0, messageCode.length); + NSUInteger numberOfMatches = [sMessageCodeRegex numberOfMatchesInString:messageCode + options:0 + range:messageCodeRange]; + NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); +#endif + NSString *logMsg; + if (args_ptr == NULL) { + logMsg = message; + } else { + logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; + } + logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; + dispatch_async(sGULClientQueue, ^{ + asl_log(sGULLoggerClient, NULL, (int)level, "%s", logMsg.UTF8String); + }); +} +#pragma clang diagnostic pop + +/** + * Generates the logging functions using macros. + * + * Calling GULLogError({service}, @"I-XYZ000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure blah failed. + * Calling GULLogDebug({service}, @"I-XYZ000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure succeed. + */ +#define GUL_LOGGING_FUNCTION(level) \ + void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ + NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +GUL_LOGGING_FUNCTION(Error) +GUL_LOGGING_FUNCTION(Warning) +GUL_LOGGING_FUNCTION(Notice) +GUL_LOGGING_FUNCTION(Info) +GUL_LOGGING_FUNCTION(Debug) + +#undef GUL_MAKE_LOGGER + +#pragma mark - GULLoggerWrapper + +@implementation GULLoggerWrapper + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + GULLogBasic(level, service, NO, messageCode, message, args); +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h new file mode 100644 index 00000000..ff425768 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The services used in the logger. + */ +typedef NSString *const GULLoggerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initialize GULLogger. + */ +extern void GULLoggerInitializeASL(void); + +/** + * Override log level to Debug. + */ +void GULLoggerForceDebug(void); + +/** + * Turn on logging to STDERR. + */ +extern void GULLoggerEnableSTDERR(void); + +/** + * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. + * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); + +/** + * Register version to include in logs. + * (required) version + */ +extern void GULLoggerRegisterVersion(const char *version); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type GULLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void GULLogError(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogWarning(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogNotice(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogInfo(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogDebug(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface GULLoggerWrapper : NSObject + +/** + * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h new file mode 100644 index 00000000..f0ee435b --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, GULLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + GULLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + GULLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + GULLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + GULLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + GULLoggerLevelDebug = 7, + /** Minimum log level. */ + GULLoggerLevelMin = GULLoggerLevelError, + /** Maximum log level. */ + GULLoggerLevelMax = GULLoggerLevelDebug +} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m new file mode 100644 index 00000000..27d48bbf --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -0,0 +1,153 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h" + +#import + +#ifdef DEBUG +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]"; +#endif + +dispatch_queue_t GetGULSwizzlingQueue(void) { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +@implementation GULSwizzler + ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block { + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + Class resolvedClass = aClass; + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + resolvedClass = object_getClass(aClass); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + IMP newImp = imp_implementationWithBlock(block); +#ifdef DEBUG + IMP currentImp = class_getMethodImplementation(resolvedClass, selector); + Class class = NSClassFromString(@"GULSwizzlingCache"); + if (class) { + SEL cacheSelector = NSSelectorFromString(@"cacheCurrentIMP:forNewIMP:forClass:withSelector:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:cacheSelector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:cacheSelector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv setArgument:&(newImp) atIndex:3]; + [inv setArgument:&(resolvedClass) atIndex:4]; + [inv setArgument:(void *_Nonnull) & (selector) atIndex:5]; + [inv invoke]; + } + } +#endif + + const char *typeEncoding = method_getTypeEncoding(method); + __unused IMP originalImpOfClass = + class_replaceMethod(resolvedClass, selector, newImp, typeEncoding); + +#ifdef DEBUG + // If !originalImpOfClass, then the IMP came from a superclass. + if (originalImpOfClass) { + SEL selector = NSSelectorFromString(@"originalIMPOfCurrentIMP:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:selector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv invoke]; + IMP testOriginal; + [inv getReturnValue:&testOriginal]; + if (originalImpOfClass != testOriginal) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeMethodSwizzling000], + @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + } + } + } +#endif + }); +} + ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + if (selector == NULL || aClass == nil) { + return nil; + } + __block IMP currentIMP = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + if (method == nil) { + return; + } + currentIMP = method_getImplementation(method); + NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + }); + return currentIMP; +} + ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector { + Method method = isClassSelector ? class_getClassMethod(aClass, selector) + : class_getInstanceMethod(aClass, selector); + return method != nil; +} + ++ (NSArray *)ivarObjectsForObject:(id)object { + NSMutableArray *array = [NSMutableArray array]; + unsigned int count; + Ivar *vars = class_copyIvarList([object class], &count); + for (NSUInteger i = 0; i < count; i++) { + const char *typeEncoding = ivar_getTypeEncoding(vars[i]); + // Check to see if the ivar is an object. + if (strncmp(typeEncoding, "@", 1) == 0) { + id ivarObject = object_getIvar(object, vars[i]); + [array addObject:ivarObject]; + } + } + free(vars); + return array; +} +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h new file mode 100644 index 00000000..a33262af --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h @@ -0,0 +1,207 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GULOriginalIMPConvenienceMacros.h + * + * This header contains convenience macros for invoking the original IMP of a swizzled method. + */ + +/** + * Invokes original IMP when the original selector takes no arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + */ +#define GUL_INVOKE_ORIGINAL_IMP0(__receivingObject, __swizzledSEL, __returnType, __originalIMP) \ + ((__returnType(*)(id, SEL))__originalIMP)(__receivingObject, __swizzledSEL) + +/** + * Invokes original IMP when the original selector takes 1 argument. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP1(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1)))__originalIMP)(__receivingObject, __swizzledSEL, \ + __arg1) + +/** + * Invokes original IMP when the original selector takes 2 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP2(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2) + +/** + * Invokes original IMP when the original selector takes 3 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP3(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), \ + __typeof__(__arg3)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3) + +/** + * Invokes original IMP when the original selector takes 4 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP4(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3, __arg4) + +/** + * Invokes original IMP when the original selector takes 5 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP5(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5) + +/** + * Invokes original IMP when the original selector takes 6 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP6(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) + +/** + * Invokes original IMP when the original selector takes 7 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP7(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) + +/** + * Invokes original IMP when the original selector takes 8 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP8(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8) + +/** + * Invokes original IMP when the original selector takes 9 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + * @param __arg9 The ninth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP9(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, \ + __arg9) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8), __typeof__(__arg9)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8, __arg9) diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h new file mode 100644 index 00000000..26949c88 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class handles the runtime manipulation necessary to instrument selectors. It stores the + * classes and selectors that have been swizzled, and runs all operations on its own queue. + */ +@interface GULSwizzler : NSObject + +/** Manipulates the Objective-C runtime to replace the original IMP with the supplied block. + * + * @param aClass The class to swizzle. + * @param selector The selector of the class to swizzle. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @param block The block that replaces the original IMP. + */ ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block; + +/** Returns the current IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime. + */ ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Checks the runtime to see if a selector exists on a class. If a property is declared as + * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists + * only in concrete subclasses, and NOT in the superclass. We can detect that situation using + * this helper method. Similarly, we can detect situations where a class doesn't implement a + * protocol method. + * + * @param selector The selector to check for. + * @param aClass The class to check. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return YES if the method was found in this selector/class combination, NO otherwise. + */ ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector; + +/** Returns a list of all Objective-C (and not primitive) ivars contained by the given object. + * + * @param object The object whose ivars will be iterated. + * @return The list of ivar objects. + */ ++ (NSArray *)ivarObjectsForObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h new file mode 100644 index 00000000..36f94a70 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h @@ -0,0 +1,49 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. + +// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given +// such data. To handle data of that size you really should be streaming it rather then doing it all +// in memory. + +@interface NSData (GULGzip) + +/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must +/// be a gzipped payloads. ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; + +/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default +/// compression level. ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; + +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber +FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber + +typedef NS_ENUM(NSInteger, GULNSDataZlibError) { + GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, + // An internal zlib error. + // GULNSDataZlibErrorKey will contain the error value. + // NSLocalizedDescriptionKey may contain an error string from zlib. + // Look in zlib.h for list of errors. + GULNSDataZlibErrorInternal, + // There was left over data in the buffer that was not used. + // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. + GULNSDataZlibErrorDataRemaining +}; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m new file mode 100644 index 00000000..5a77bb8f --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -0,0 +1,207 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/NSData+zlib/GULNSData+zlib.h" + +#import + +#define kChunkSize 1024 +#define Z_DEFAULT_COMPRESSION (-1) + +NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; +NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; +NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; + +@implementation NSData (GULGzip) + ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 4x the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; + unsigned char output[kChunkSize]; + + // Loop to collect the data. + do { + // Update what we're passing in. + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + if (strm.msg) { + NSString *message = [NSString stringWithUTF8String:strm.msg]; + if (message) { + [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; + } + } + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + inflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // Make sure there wasn't more data tacked onto the end of a valid compressed stream. + if (strm.avail_in != 0) { + if (error) { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] + forKey:GULNSDataZlibRemainingBytesKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorDataRemaining + userInfo:userInfo]; + } + result = nil; + } + // The only way out of the loop was by hitting the end of the stream. + NSAssert(retCode == Z_STREAM_END, + @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + inflateEnd(&strm); + + return result; +} + ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + if (error) { + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorGreaterThan32BitsToCompress + userInfo:nil]; + } + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m new file mode 100644 index 00000000..43896601 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m @@ -0,0 +1,101 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" + +@implementation GULMutableDictionary { + /// The mutable dictionary. + NSMutableDictionary *_objects; + + /// Serial synchronization queue. All reads should use dispatch_sync, while writes use + /// dispatch_async. + dispatch_queue_t _queue; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _objects = [[NSMutableDictionary alloc] init]; + _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (NSString *)description { + __block NSString *description; + dispatch_sync(_queue, ^{ + description = self->_objects.description; + }); + return description; +} + +- (id)objectForKey:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = [self->_objects objectForKey:key]; + }); + return object; +} + +- (void)setObject:(id)object forKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects setObject:object forKey:key]; + }); +} + +- (void)removeObjectForKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_async(_queue, ^{ + [self->_objects removeAllObjects]; + }); +} + +- (NSUInteger)count { + __block NSUInteger count; + dispatch_sync(_queue, ^{ + count = self->_objects.count; + }); + return count; +} + +- (id)objectForKeyedSubscript:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = self->_objects[key]; + }); + return object; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + dispatch_async(_queue, ^{ + self->_objects[key] = obj; + }); +} + +- (NSDictionary *)dictionary { + __block NSDictionary *dictionary; + dispatch_sync(_queue, ^{ + dictionary = [self->_objects copy]; + }); + return dictionary; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m new file mode 100644 index 00000000..9d78e0ef --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -0,0 +1,389 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetwork.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +#import +#import +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +/// Constant string for request header Content-Encoding. +static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; + +/// Constant string for request header Content-Encoding value. +static NSString *const kGULNetworkContentCompressionValue = @"gzip"; + +/// Constant string for request header Content-Length. +static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; + +/// Constant string for request header Content-Type. +static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; + +/// Constant string for request header Content-Type value. +static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; + +/// Constant string for GET request method. +static NSString *const kGULNetworkGETRequestMethod = @"GET"; + +/// Constant string for POST request method. +static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; + +/// Default constant string as a prefix for network logger. +static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; + +@interface GULNetwork () +@end + +@implementation GULNetwork { + /// Network reachability. + GULReachabilityChecker *_reachability; + + /// The dictionary of requests by session IDs { NSString : id }. + GULMutableDictionary *_requests; +} + +- (instancetype)init { + return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; +} + +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { + self = [super init]; + if (self) { + // Setup reachability. + _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:reachabilityHost]; + if (![_reachability start]) { + return nil; + } + + _requests = [[GULMutableDictionary alloc] init]; + _timeoutInterval = kGULNetworkTimeOutInterval; + } + return self; +} + +- (void)dealloc { + _reachability.reachabilityDelegate = nil; + [_reachability stop]; +} + +#pragma mark - External Methods + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { + [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID + completionHandler:completionHandler]; +} + +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + NSError *compressError = nil; + NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; + if (!compressedData || compressError) { + if (compressError || payload.length > 0) { + // If the payload is not empty but it fails to compress the payload, something has been wrong. + [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression + queue:queue + withHandler:handler]; + return nil; + } + compressedData = [[NSData alloc] init]; + } + + NSString *postLength = @(compressedData.length).stringValue; + + // Set up the request with the compressed data. + [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; + request.HTTPBody = compressedData; + request.HTTPMethod = kGULNetworkPOSTRequestMethod; + [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; + [request setValue:kGULNetworkContentCompressionValue + forHTTPHeaderField:kGULNetworkContentCompressionKey]; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncPOSTRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, + NSString *sessionID, NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork000 + message:@"Uploading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + request.HTTPMethod = kGULNetworkGETRequestMethod; + request.allHTTPHeaderFields = headers; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncGETRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, + NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork001 + message:@"Downloading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (BOOL)hasUploadInProgress { + return _requests.count > 0; +} + +#pragma mark - Network Reachability + +/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network +/// reachability has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); + [_reachabilityDelegate reachabilityDidChange]; +} + +#pragma mark - Network logger delegate + +- (void)setLoggerDelegate:(id)loggerDelegate { + // Explicitly check whether the delegate responds to the methods because conformsToProtocol does + // not work correctly even though the delegate does respond to the methods. + if (!loggerDelegate || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:contexts:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:context:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:)]) { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], + @"Cannot set the network logger delegate: delegate does not conform to the network " + "logger protocol."); + return; + } + _loggerDelegate = loggerDelegate; +} + +#pragma mark - Private methods + +/// Handles network error and calls completion handler with the error. +- (void)handleErrorWithCode:(NSInteger)code + queue:(dispatch_queue_t)queue + withHandler:(GULNetworkCompletionHandler)handler { + NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; + NSError *error = [[NSError alloc] initWithDomain:kGULNetworkErrorDomain + code:code + userInfo:userInfo]; + [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeNetwork002 + message:@"Failed to create network request. Code, error" + contexts:@[ @(code), error ]]; + if (handler) { + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + handler(nil, nil, error); + }); + } +} + +#pragma mark - Network logger + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts { + // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log + // errors/warnings/info messages to the console log. + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + contexts:contexts]; + return; + } + if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || + logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { + NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); + NSLog(@"%@", formattedMessage); + GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, + NULL); + } +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + context:context]; + return; + } + NSArray *contexts = context ? @[ context ] : @[]; + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; + return; + } + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; +} + +/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). +static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { + static NSDictionary *levelNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelNames = @{ + @(kGULNetworkLogLevelError) : @"ERROR", + @(kGULNetworkLogLevelWarning) : @"WARNING", + @(kGULNetworkLogLevelInfo) : @"INFO", + @(kGULNetworkLogLevelDebug) : @"DEBUG" + }; + }); + return levelNames[@(logLevel)]; +} + +/// Returns a formatted string to be used for console logging. +static NSString *GULStringWithLogMessage(NSString *message, + GULNetworkLogLevel logLevel, + NSArray *contexts) { + if (!message) { + message = @"(Message was nil)"; + } else if (!message.length) { + message = @"(Message was empty)"; + } + NSMutableString *result = [[NSMutableString alloc] + initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), + message]; + + if (!contexts.count) { + return result; + } + + NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; + for (id item in contexts) { + [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; + } + + [result appendString:@": "]; + [result appendString:[formattedContexts componentsJoinedByString:@", "]]; + return result; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m new file mode 100644 index 00000000..dea8dbd5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m @@ -0,0 +1,40 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +#import + +NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; +NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; +NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; +const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour +const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. +NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; +NSString *const kGULNetworkErrorContext = @"Context"; + +const int kGULNetworkHTTPStatusOK = 200; +const int kGULNetworkHTTPStatusNoContent = 204; +const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; +const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; +const int kGULNetworkHTTPStatusCodeFound = 302; +const int kGULNetworkHTTPStatusCodeNotModified = 304; +const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; +const int kGULNetworkHTTPStatusCodeNotFound = 404; +const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; +const int kGULNetworkHTTPStatusCodeUnavailable = 503; + +NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; + +GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m new file mode 100644 index 00000000..df8bf460 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -0,0 +1,762 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h" + +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +@interface GULNetworkURLSession () +@end + +@implementation GULNetworkURLSession { + /// The handler to be called when the request completes or error has occurs. + GULNetworkURLSessionCompletionHandler _completionHandler; + + /// Session ID generated randomly with a fixed prefix. + NSString *_sessionID; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + /// The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer. + NSURLSessionConfiguration *_sessionConfig; + + /// The current NSURLSession. + NSURLSession *__weak _Nullable _URLSession; +#pragma clang diagnostic pop + + /// The path to the directory where all temporary files are stored before uploading. + NSURL *_networkDirectoryURL; + + /// The downloaded data from fetching. + NSData *_downloadedData; + + /// The path to the temporary file which stores the uploading data. + NSURL *_uploadingFileURL; + + /// The current request. + NSURLRequest *_request; +} + +#pragma mark - Init + +- (instancetype)initWithNetworkLoggerDelegate:(id)networkLoggerDelegate { + self = [super init]; + if (self) { + // Create URL to the directory where all temporary files to upload have to be stored. + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportDirectory = paths.firstObject; + NSArray *tempPathComponents = @[ + applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, + kGULNetworkTempDirectoryName + ]; + _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; + _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, + [[NSUUID UUID] UUIDString]]; + _loggerDelegate = networkLoggerDelegate; + } + return self; +} + +#pragma mark - External Methods + +#pragma mark - To be called from AppDelegate + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler: + (GULNetworkSystemCompletionHandler)systemCompletionHandler { + // The session may not be Analytics background. Ignore those that do not have the prefix. + if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + return; + } + GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; + if (fetcher != nil) { + [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; + } else { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], + @"Failed to retrieve background session with ID %@ after app is relaunched.", + sessionID); + } +} + +#pragma mark - External Methods + +/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the +/// connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + // NSURLSessionUploadTask does not work with NSData in the background. + // To avoid this issue, write the data to a temporary file to upload it. + // Make a temporary file with the data subset. + _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; + NSError *writeError; + NSURLSessionUploadTask *postRequestTask; + NSURLSession *session; + BOOL didWriteFile = NO; + + // Clean up the entire temp folder to avoid temp files that remain in case the previous session + // crashed and did not clean up. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // If there is no background network enabled, no need to write to file. This will allow default + // network session which runs on the foreground. + if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { + didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path + options:NSDataWritingAtomic + error:&writeError]; + + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession000 + message:@"Failed to write request data to file" + context:writeError]; + } + } + + if (didWriteFile) { + // Exclude this file from backing up to iTunes. There are conflicting reports that excluding + // directory from backing up does not exclude files of that directory from backing up. + [self excludeFromBackupForURL:_uploadingFileURL]; + + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; + } else { + // If we cannot write to file, just send it in the foreground. + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; + } + + if (!session || !postRequestTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + // Store completion handler because background session does not accept handler block but custom + // delegate. + _completionHandler = [handler copy]; + [postRequestTask resume]; + + return _sessionID; +} + +/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + if (_backgroundNetworkEnabled) { + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + } else { + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + } + + [self populateSessionConfig:_sessionConfig withRequest:request]; + + // Do not cache the GET request. + _sessionConfig.URLCache = nil; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; + + if (!session || !downloadTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + _completionHandler = [handler copy]; + [downloadTask resume]; + + return _sessionID; +} + +#pragma mark - NSURLSessionDataDelegate + +/// Called by the NSURLSession when the data task has received some of the expected data. +/// Once the session is completed, URLSession:task:didCompleteWithError will be called and the +/// completion handler will be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + @synchronized(self) { + NSMutableData *mutableData = [[NSMutableData alloc] init]; + if (_downloadedData) { + mutableData = _downloadedData.mutableCopy; + } + [mutableData appendData:data]; + _downloadedData = mutableData; + } +} + +#pragma mark - NSURLSessionTaskDelegate + +/// Called by the NSURLSession once the download task is completed. The file is saved in the +/// provided URL so we need to read the data and store into _downloadedData. Once the session is +/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will +/// be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:(NSURL *)url API_AVAILABLE(ios(7.0)) { + if (!url.path) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession001 + message:@"Unable to read downloaded data from empty temp path"]; + _downloadedData = nil; + return; + } + + NSError *error; + _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; + + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession002 + message:@"Cannot read the content of downloaded data" + context:error]; + _downloadedData = nil; + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session + API_AVAILABLE(ios(7.0)) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession003 + message:@"Background session finished" + context:session.configuration.identifier]; + [self callSystemCompletionHandler:session.configuration.identifier]; +} +#endif + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(7.0)) { + // Avoid any chance of recursive behavior leading to it being used repeatedly. + GULNetworkURLSessionCompletionHandler handler = _completionHandler; + _completionHandler = nil; + + if (task.response) { + // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. + NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); + + // The server responded so ignore the error created by the system. + error = nil; + } else if (!error) { + error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkInvalidResponse + userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; + } + + [self callCompletionHandler:handler + withResponse:(NSHTTPURLResponse *)task.response + data:_downloadedData + error:error]; + + // Remove the temp file to avoid trashing devices with lots of temp files. + [self removeTempItemAtURL:_uploadingFileURL]; + + // Try to clean up stale files again. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // This is called without checking the sessionID here since non-background sessions + // won't have an ID. + [session finishTasksAndInvalidate]; + + // Explicitly remove the session so it won't be reused. The weak map table should + // remove the session on deallocation, but dealloc may not happen immediately after + // calling `finishTasksAndInvalidate`. + NSString *sessionID = session.configuration.identifier; + [[self class] setSessionInFetcherMap:nil forSessionID:sessionID]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential))completionHandler + API_AVAILABLE(ios(7.0)) { + // The handling is modeled after GTMSessionFetcher. + if ([challenge.protectionSpace.authenticationMethod + isEqualToString:NSURLAuthenticationMethodServerTrust]) { + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession004 + message:@"Received empty server trust for host. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + if (!credential) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession005 + message:@"Unable to verify server identity. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession006 + message:@"Received SSL challenge for host. Host" + context:_request.URL]; + + void (^callback)(BOOL) = ^(BOOL allow) { + if (allow) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + [self->_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession007 + message:@"Cancelling authentication challenge for host. Host" + context:self->_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_async(evaluateBackgroundQueue, ^{ + SecTrustResultType trustEval = kSecTrustResultInvalid; + BOOL shouldAllow; + OSStatus trustError; + + @synchronized([GULNetworkURLSession class]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + trustError = SecTrustEvaluate(serverTrust, &trustEval); +#pragma clang dianostic pop + } + + if (trustError != errSecSuccess) { + [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession008 + message:@"Cannot evaluate server trust. Error, host" + contexts:@[ @(trustError), self->_request.URL ]]; + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + shouldAllow = + (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); + } + + // Call the call back with the permission. + callback(shouldAllow); + + CFRelease(serverTrust); + }); + return; + } + + // Default handling for other Auth Challenges. + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + +#pragma mark - Internal Methods + +/// Stores system completion handler with session ID as key. +- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler + forSession:(NSString *)identifier { + if (!handler) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession009 + message:@"Cannot store nil system completion handler in network"]; + return; + } + + if (!identifier.length) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession010 + message:@"Cannot store system completion handler with empty network " + "session identifier"]; + return; + } + + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + if (systemCompletionHandlers[identifier]) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession011 + message:@"Got multiple system handlers for a single session ID" + context:identifier]; + } + + systemCompletionHandlers[identifier] = handler; +} + +/// Calls the system provided completion handler with the session ID stored in the dictionary. +/// The handler will be removed from the dictionary after being called. +- (void)callSystemCompletionHandler:(NSString *)identifier { + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; + + if (handler) { + [systemCompletionHandlers removeObjectForKey:identifier]; + + dispatch_async(dispatch_get_main_queue(), ^{ + handler(); + }); + } +} + +/// Sets or updates the session ID of this session. +- (void)setSessionID:(NSString *)sessionID { + _sessionID = [sessionID copy]; +} + +/// Creates a background session configuration with the session ID using the supported method. +- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID + API_AVAILABLE(ios(7.0)) { +#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ + TARGET_OS_TV || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) + + // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; + +#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) + + // Do a runtime check to avoid a deprecation warning about using + // +backgroundSessionConfiguration: on iOS 8. + if ([NSURLSessionConfiguration + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + // Running on iOS 8+/OS X 10.10+. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; +#pragma clang diagnostic pop + } else { + // Running on iOS 7/OS X 10.9. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; + } + +#else + // Building with an SDK earlier than iOS 8/OS X 10.10. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; +#endif +} + +- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { + if (!folderURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + NSArray *properties = @[ NSURLCreationDateKey ]; + NSArray *directoryContent = + [fileManager contentsOfDirectoryAtURL:folderURL + includingPropertiesForKeys:properties + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants + error:&error]; + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession012 + message:@"Cannot get files from the temporary network folder. Error" + context:error]; + return; + } + + if (!directoryContent.count) { + return; + } + + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + for (NSURL *tempFile in directoryContent) { + NSDate *creationDate; + BOOL getCreationDate = [tempFile getResourceValue:&creationDate + forKey:NSURLCreationDateKey + error:NULL]; + if (!getCreationDate) { + continue; + } + NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; + if (fabs(now - creationTimeInterval) > staleTime) { + [self removeTempItemAtURL:tempFile]; + } + } +} + +/// Removes the temporary file written to disk for sending the request. It has to be cleaned up +/// after the session is done. +- (void)removeTempItemAtURL:(NSURL *)fileURL { + if (!fileURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession013 + message:@"Failed to remove temporary uploading data file. Error" + context:error.localizedDescription]; + } +} + +/// Gets the fetcher with the session ID. ++ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID:sessionIdentifier]; + if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; + [session setSessionID:sessionIdentifier]; + [self setSessionInFetcherMap:session forSessionID:sessionIdentifier]; + } + return session; +} + +/// Returns a map of the fetcher by session ID. Creates a map if it is not created. +/// When reading and writing from/to the session map, don't use this method directly. +/// To avoid thread safety issues, use one of the helper methods at the bottom of the +/// file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID: ++ (NSMapTable *)sessionIDToFetcherMap { + static NSMapTable *sessionIDToFetcherMap; + + static dispatch_once_t sessionMapOnceToken; + dispatch_once(&sessionMapOnceToken, ^{ + sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return sessionIDToFetcherMap; +} + ++ (NSLock *)sessionIDToFetcherMapReadWriteLock { + static NSLock *lock; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + return lock; +} + +/// Returns a map of system provided completion handler by session ID. Creates a map if it is not +/// created. ++ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { + static GULMutableDictionary *systemCompletionHandlers; + + static dispatch_once_t systemCompletionHandlerOnceToken; + dispatch_once(&systemCompletionHandlerOnceToken, ^{ + systemCompletionHandlers = [[GULMutableDictionary alloc] init]; + }); + return systemCompletionHandlers; +} + +- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { + NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; + return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; +} + +/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns +/// YES. If there is anything wrong, returns NO. +- (BOOL)ensureTemporaryDirectoryExists { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + // Create a temporary directory if it does not exist or was deleted. + if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + return YES; + } + + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession014 + message:@"Error while trying to access Network temp folder. Error" + context:error]; + } + + NSError *writeError = nil; + + [fileManager createDirectoryAtURL:_networkDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&writeError]; + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession015 + message:@"Cannot create temporary directory. Error" + context:writeError]; + return NO; + } + + // Set the iCloud exclusion attribute on the Documents URL. + [self excludeFromBackupForURL:_networkDirectoryURL]; + + return YES; +} + +- (void)excludeFromBackupForURL:(NSURL *)url { + if (!url.path) { + return; + } + + // Set the iCloud exclusion attribute on the Documents URL. + NSError *preventBackupError = nil; + [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; + if (preventBackupError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession016 + message:@"Cannot exclude temporary folder from iTunes backup"]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler API_AVAILABLE(ios(7.0)) { + NSArray *nonAllowedRedirectionCodes = @[ + @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), + @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) + ]; + + // Allow those not in the non allowed list to be followed. + if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { + completionHandler(request); + return; + } + + // Do not allow redirection if the response code is in the non-allowed list. + NSURLRequest *newRequest = request; + + if (response) { + newRequest = nil; + } + + completionHandler(newRequest); +} + +#pragma mark - Helper Methods + ++ (void)setSessionInFetcherMap:(GULNetworkURLSession *)session forSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *existingSession = + [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + if (existingSession) { + if (session) { + NSString *message = [NSString stringWithFormat:@"Discarding session: %@", existingSession]; + [existingSession->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelInfo + messageCode:kGULNetworkMessageCodeURLSession019 + message:message]; + } + [existingSession->_URLSession finishTasksAndInvalidate]; + } + if (session) { + [[[self class] sessionIDToFetcherMap] setObject:session forKey:sessionID]; + } else { + [[[self class] sessionIDToFetcherMap] removeObjectForKey:sessionID]; + } + [[self sessionIDToFetcherMapReadWriteLock] unlock]; +} + ++ (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *session = [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + [[self sessionIDToFetcherMapReadWriteLock] unlock]; + return session; +} + +- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler + withResponse:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession017 + message:@"Encounter network error. Code, error" + contexts:@[ @(error.code), error ]]; + } + + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(response, data, self->_sessionID, error); + }); + } +} + +// Always use the request parameters even if the default session configuration is more restrictive. +- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig + withRequest:(NSURLRequest *)request API_AVAILABLE(ios(7.0)) { + sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; + sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; + sessionConfig.timeoutIntervalForResource = request.timeoutInterval; + sessionConfig.requestCachePolicy = request.cachePolicy; +} + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h new file mode 100644 index 00000000..a8cc45b4 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// A mutable dictionary that provides atomic accessor and mutators. +@interface GULMutableDictionary : NSObject + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKey:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)object forKey:(id)key; + +/// Removes the object given its session ID from the dictionary. +- (void)removeObjectForKey:(id)key; + +/// Removes all objects. +- (void)removeAllObjects; + +/// Returns the number of current objects in the dictionary. +- (NSUInteger)count; + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKeyedSubscript:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key; + +/// Returns the immutable dictionary. +- (NSDictionary *)dictionary; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h new file mode 100644 index 00000000..0e75ae5d --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkConstants.h" +#import "GULNetworkLoggerProtocol.h" +#import "GULNetworkURLSession.h" + +/// Delegate protocol for GULNetwork events. +@protocol GULNetworkReachabilityDelegate + +/// Tells the delegate to handle events when the network reachability changes to connected or not +/// connected. +- (void)reachabilityDidChange; + +@end + +/// The Network component that provides network status and handles network requests and responses. +/// This is not thread safe. +/// +/// NOTE: +/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the +/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: +@interface GULNetwork : NSObject + +/// Indicates if network connectivity is available. +@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; + +/// Indicates if there are any uploads in progress. +@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; + +/// An optional delegate that can be used in the event when network reachability changes. +@property(nonatomic, weak) id reachabilityDelegate; + +/// An optional delegate that can be used to log messages, warnings or errors that occur in the +/// network operations. +@property(nonatomic, weak) id loggerDelegate; + +/// Indicates whether the logger should display debug messages. +@property(nonatomic, assign) BOOL isDebugModeEnabled; + +/// The time interval in seconds for the network request to timeout. +@property(nonatomic, assign) NSTimeInterval timeoutInterval; + +/// Initializes with the default reachability host. +- (instancetype)init; + +/// Initializes with a custom reachability host. +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; + +/// Handles events when background session with the given ID has finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Compresses and sends a POST request with the provided data to the URL. The session will be +/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default +/// session. Returns a session ID or nil if an error occurs. +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +/// Sends a GET request with the provided data to the URL. The session will be background session +/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a +/// session ID or nil if an error occurs. +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h new file mode 100644 index 00000000..44d440b9 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Error codes in Firebase Network error domain. +/// Note: these error codes should never change. It would make it harder to decode the errors if +/// we inadvertently altered any of these codes in a future SDK version. +typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { + /// Unknown error. + GULNetworkErrorCodeUnknown = 0, + /// Error occurs when the request URL is invalid. + GULErrorCodeNetworkInvalidURL = 1, + /// Error occurs when request cannot be constructed. + GULErrorCodeNetworkRequestCreation = 2, + /// Error occurs when payload cannot be compressed. + GULErrorCodeNetworkPayloadCompression = 3, + /// Error occurs when session task cannot be created. + GULErrorCodeNetworkSessionTaskCreation = 4, + /// Error occurs when there is no response. + GULErrorCodeNetworkInvalidResponse = 5 +}; + +#pragma mark - Network constants + +/// The prefix of the ID of the background session. +extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; + +/// The sub directory to store the files of data that is being uploaded in the background. +extern NSString *const kGULNetworkApplicationSupportSubdirectory; + +/// Name of the temporary directory that stores files for background uploading. +extern NSString *const kGULNetworkTempDirectoryName; + +/// The period when the temporary uploading file can stay. +extern const NSTimeInterval kGULNetworkTempFolderExpireTime; + +/// The default network request timeout interval. +extern const NSTimeInterval kGULNetworkTimeOutInterval; + +/// The host to check the reachability of the network. +extern NSString *const kGULNetworkReachabilityHost; + +/// The key to get the error context of the UserInfo. +extern NSString *const kGULNetworkErrorContext; + +#pragma mark - Network Status Code + +extern const int kGULNetworkHTTPStatusOK; +extern const int kGULNetworkHTTPStatusNoContent; +extern const int kGULNetworkHTTPStatusCodeMultipleChoices; +extern const int kGULNetworkHTTPStatusCodeMovedPermanently; +extern const int kGULNetworkHTTPStatusCodeFound; +extern const int kGULNetworkHTTPStatusCodeNotModified; +extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; +extern const int kGULNetworkHTTPStatusCodeNotFound; +extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; +extern const int kGULNetworkHTTPStatusCodeUnavailable; + +#pragma mark - Error Domain + +extern NSString *const kGULNetworkErrorDomain; + +/// The logger service for GULNetwork. +extern GULLoggerService kGULLoggerNetwork; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h new file mode 100644 index 00000000..f1be5906 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GULNetworkMessageCode.h" + +/// The log levels used by GULNetworkLogger. +typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { + kGULNetworkLogLevelError = GULLoggerLevelError, + kGULNetworkLogLevelWarning = GULLoggerLevelWarning, + kGULNetworkLogLevelInfo = GULLoggerLevelInfo, + kGULNetworkLogLevelDebug = GULLoggerLevelDebug, +}; + +@protocol GULNetworkLoggerDelegate + +@required +/// Tells the delegate to log a message with an array of contexts and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts; + +/// Tells the delegate to log a message with a context and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context; + +/// Tells the delegate to log a message with the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h new file mode 100644 index 00000000..507bc5a5 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { + // GULNetwork.m + kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 + kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 + kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 + kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 + // GULNetworkURLSession.m + kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 + kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 + kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 + kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 + kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 + kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 + kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 + kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 + kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 + kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 + kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 + kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 + kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 + kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 + kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 + kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 + kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 + kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 + kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 + kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019 +}; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h new file mode 100644 index 00000000..3f9f7f9e --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkLoggerProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSError *_Nullable error); +typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSString *sessionID, + NSError *_Nullable error); +typedef void (^GULNetworkSystemCompletionHandler)(void); + +/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. +@interface GULNetworkURLSession : NSObject + +/// Indicates whether the background network is enabled. Default value is NO. +@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; + +/// The logger delegate to log message, errors or warnings that occur during the network operations. +@property(nonatomic, weak, nullable) id loggerDelegate; + +/// Calls the system provided completion handler after the background session is finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Initializes with logger delegate. +- (instancetype)initWithNetworkLoggerDelegate: + (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Sends an asynchronous POST request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session/connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +/// Sends an asynchronous GET request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +NS_ASSUME_NONNULL_END +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h new file mode 100644 index 00000000..8aabc8a1 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, + const char *host); + +typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context); +typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); +typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); + +typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); + +struct GULReachabilityApi { + GULReachabilityCreateWithNameFn createWithNameFn; + GULReachabilitySetCallbackFn setCallbackFn; + GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; + GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; + GULReachabilityReleaseFn releaseFn; +}; +#endif +@interface GULReachabilityChecker (Internal) + +- (const struct GULReachabilityApi *)reachabilityApi; +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m new file mode 100644 index 00000000..a334c1a0 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -0,0 +1,263 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h" + +#import +#import + +static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +static const struct GULReachabilityApi kGULDefaultReachabilityApi = { + SCNetworkReachabilityCreateWithName, + SCNetworkReachabilitySetCallback, + SCNetworkReachabilityScheduleWithRunLoop, + SCNetworkReachabilityUnscheduleFromRunLoop, + CFRelease, +}; + +static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; +static NSString *const kGULReachabilityConnectedStatus = @"Connected"; +static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; +#endif +@interface GULReachabilityChecker () + +@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; +@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; +@property(nonatomic, copy) NSString *host; +#if !TARGET_OS_WATCH +@property(nonatomic, assign) SCNetworkReachabilityRef reachability; +#endif + +@end + +@implementation GULReachabilityChecker + +@synthesize reachabilityApi = reachabilityApi_; +#if !TARGET_OS_WATCH +@synthesize reachability = reachability_; +#endif + +- (const struct GULReachabilityApi *)reachabilityApi { + return reachabilityApi_; +} + +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { +#if !TARGET_OS_WATCH + if (reachability_) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], + @"Cannot change reachability API while reachability is running. " + @"Call stop first."); + return; + } + reachabilityApi_ = reachabilityApi; +#endif +} + +@synthesize reachabilityStatus = reachabilityStatus_; +@synthesize host = host_; +@synthesize reachabilityDelegate = reachabilityDelegate_; + +- (BOOL)isActive { +#if !TARGET_OS_WATCH + return reachability_ != nil; +#else + return NO; +#endif +} + +- (void)setReachabilityDelegate:(id)reachabilityDelegate { + if (reachabilityDelegate && + (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], + @"Reachability delegate doesn't conform to Reachability protocol."); + return; + } + reachabilityDelegate_ = reachabilityDelegate; +} + +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host { + self = [super init]; + + if (!host || !host.length) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], + @"Invalid host specified"); + return nil; + } + if (self) { +#if !TARGET_OS_WATCH + [self setReachabilityDelegate:reachabilityDelegate]; + reachabilityApi_ = &kGULDefaultReachabilityApi; + reachabilityStatus_ = kGULReachabilityUnknown; + host_ = [host copy]; + reachability_ = nil; +#endif + } + return self; +} + +- (void)dealloc { + reachabilityDelegate_ = nil; + [self stop]; +} + +- (BOOL)start { +#if TARGET_OS_WATCH + return NO; +#else + + if (!reachability_) { + reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); + if (!reachability_) { + return NO; + } + SCNetworkReachabilityContext context = { + 0, /* version */ + (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ + NULL, /* retain */ + NULL, /* release */ + NULL /* copyDescription */ + }; + if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || + !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes)) { + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], + @"Failed to start reachability handle"); + return NO; + } + } + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], + @"Monitoring the network status"); + return YES; +#endif +} + +- (void)stop { +#if !TARGET_OS_WATCH + if (reachability_) { + reachabilityStatus_ = kGULReachabilityUnknown; + reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes); + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + } +#endif +} + +#if !TARGET_OS_WATCH +- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = kGULReachabilityNotReachable; + // If the Reachable flag is not set, we definitely don't have connectivity. + if (flags & kSCNetworkReachabilityFlagsReachable) { + // Reachable flag is set. Check further flags. + if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { +// Connection required flag is not set, so we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | + kSCNetworkReachabilityFlagsConnectionOnTraffic)) && + !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { +// If the connection on demand or connection on traffic flag is set, and user intervention +// is not required, we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } + } + return status; +} + +- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = [self statusForFlags:flags]; + if (reachabilityStatus_ != status) { + NSString *reachabilityStatusString; + if (status == kGULReachabilityUnknown) { + reachabilityStatusString = kGULReachabilityUnknownStatus; + } else { + reachabilityStatusString = (status == kGULReachabilityNotReachable) + ? kGULReachabilityDisconnectedStatus + : kGULReachabilityConnectedStatus; + } + + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], + @"Network status has changed. Code:%@, status:%@", @(status), + reachabilityStatusString); + reachabilityStatus_ = status; + [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; + } +} + +#endif +@end + +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; + [checker reachabilityFlagsChanged:flags]; +} +#endif + +// This function used to be at the top of the file, but it was moved here +// as a workaround for a suspected compiler bug. When compiled in Release mode +// and run on an iOS device with WiFi disabled, the reachability code crashed +// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. +// After unsuccessfully trying to diagnose the cause of the crash, it was +// discovered that moving this function to the end of the file magically fixed +// the crash. If you are going to edit this file, exercise caution and make sure +// to test thoroughly with an iOS device under various network conditions. +const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { + switch (status) { + case kGULReachabilityUnknown: + return @"Reachability Unknown"; + + case kGULReachabilityNotReachable: + return @"Not reachable"; + + case kGULReachabilityViaWifi: + return @"Reachable via Wifi"; + + case kGULReachabilityViaCellular: + return @"Reachable via Cellular Data"; + + default: + return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; + } +} diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h new file mode 100644 index 00000000..0c70c055 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +#import +#endif + +/// Reachability Status +typedef enum { + kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. + kGULReachabilityNotReachable, ///< Host is not reachable. + kGULReachabilityViaWifi, ///< Host is reachable via Wifi. + kGULReachabilityViaCellular, ///< Host is reachable via cellular. +} GULReachabilityStatus; + +const NSString *GULReachabilityStatusString(GULReachabilityStatus status); + +@class GULReachabilityChecker; + +/// Google Analytics iOS Reachability Checker. +@protocol GULReachabilityDelegate +@required +/// Called when network status has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status; +@end + +/// Google Analytics iOS Network Status Checker. +@interface GULReachabilityChecker : NSObject + +/// The last known reachability status, or GULReachabilityStatusUnknown if the +/// checker is not active. +@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; +/// The host to which reachability status is to be checked. +@property(nonatomic, copy, readonly) NSString *host; +/// The delegate to be notified of reachability status changes. +@property(nonatomic, weak) id reachabilityDelegate; +/// `YES` if the reachability checker is active, `NO` otherwise. +@property(nonatomic, readonly) BOOL isActive; + +/// Initialize the reachability checker. Note that you must call start to begin checking for and +/// receiving notifications about network status changes. +/// +/// @param reachabilityDelegate The delegate to be notified when reachability status to host +/// changes. +/// +/// @param host The name of the host. +/// +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host; + +- (instancetype)init NS_UNAVAILABLE; + +/// Start checking for reachability to the specified host. This has no effect if the status +/// checker is already checking for connectivity. +/// +/// @return `YES` if initiating status checking was successful or the status checking has already +/// been initiated, `NO` otherwise. +- (BOOL)start; + +/// Stop checking for reachability to the specified host. This has no effect if the status +/// checker is not checking for connectivity. +- (void)stop; + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h new file mode 100644 index 00000000..373e0af4 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) { + // GULReachabilityChecker.m + kGULReachabilityMessageCode000 = 902000, // I-NET902000 + kGULReachabilityMessageCode001 = 902001, // I-NET902001 + kGULReachabilityMessageCode002 = 902002, // I-NET902002 + kGULReachabilityMessageCode003 = 902003, // I-NET902003 + kGULReachabilityMessageCode004 = 902004, // I-NET902004 + kGULReachabilityMessageCode005 = 902005, // I-NET902005 + kGULReachabilityMessageCode006 = 902006, // I-NET902006 +}; diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m new file mode 100644 index 00000000..b80e2aff --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m @@ -0,0 +1,438 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TargetConditionals.h" + +#import +#import +#import +#import +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h" + +#import + +#if UISCENE_SUPPORTED +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (*GULOpenURLContextsIMP)(id, SEL, UIScene *, NSSet *); + +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (^GULSceneDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; +#endif // UISCENE_SUPPORTED + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/SceneDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseSceneDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the Scene Delegate. */ +static NSString *const kGULSceneDelegatePrefix = @"GUL_"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULSceneZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULSceneZeroingWeakContainer +@end + +@implementation GULSceneDelegateSwizzler + +#pragma mark - Public methods + ++ (BOOL)isSceneDelegateProxyEnabled { + return [GULAppDelegateSwizzler isAppDelegateProxyEnabled]; +} + ++ (void)proxyOriginalSceneDelegate { +#if UISCENE_SUPPORTED + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (@available(iOS 13.0, tvOS 13.0, *)) { + if (![GULSceneDelegateSwizzler isSceneDelegateProxyEnabled]) { + return; + } + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleSceneWillConnectToNotification:) + name:UISceneWillConnectNotification + object:nil]; + } + }); +#endif // UISCENE_SUPPORTED +} + +#if UISCENE_SUPPORTED ++ (GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor:(id)interceptor { + NSAssert(interceptor, @"SceneDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(UISceneDelegate)], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling000], + @"SceneDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(UISceneDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling001], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = + [NSString stringWithFormat:@"%@%p", kGULSceneDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling002], + @"SceneDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULSceneZeroingWeakContainer *weakObject = [[GULSceneZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULSceneDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"SceneDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling003], + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULSceneZeroingWeakContainer *weakContainer = + [GULSceneDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling004], + @"SceneDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULSceneDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULSceneDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULSceneDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULSceneDelegateInterceptorCallback)callback + API_AVAILABLE(ios(13.0)) { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULSceneDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULSceneZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling010], + @"SceneDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + ++ (void)handleSceneWillConnectToNotification:(NSNotification *)notification { + if (@available(iOS 13.0, tvOS 13.0, *)) { + if ([notification.object isKindOfClass:[UIScene class]]) { + UIScene *scene = (UIScene *)notification.object; + [GULSceneDelegateSwizzler proxySceneDelegateIfNeeded:scene]; + } + } +} + +#pragma mark - [Donor Methods] UISceneDelegate URL handler + +- (void)scene:(UIScene *)scene + openURLContexts:(NSSet *)URLContexts API_AVAILABLE(ios(13.0), tvos(13.0)) { + if (@available(iOS 13.0, tvOS 13.0, *)) { + SEL methodSelector = @selector(scene:openURLContexts:); + // Call the real implementation if the real Scene Delegate has any. + NSValue *openURLContextsIMPPointer = + [GULSceneDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULOpenURLContextsIMP openURLContextsIMP = [openURLContextsIMPPointer pointerValue]; + + [GULSceneDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + if ([interceptor + conformsToProtocol:@protocol(UISceneDelegate)]) { + id sceneInterceptor = + (id)interceptor; + [sceneInterceptor scene:scene openURLContexts:URLContexts]; + } + }]; + + if (openURLContextsIMP) { + openURLContextsIMP(self, methodSelector, scene, URLContexts); + } + } +} + ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene { + Class realClass = [scene.delegate class]; + NSString *className = NSStringFromClass(realClass); + + // Skip proxying if failed to get the delegate class name for some reason (e.g. `delegate == nil`) + // or the class has a prefix of kGULAppDelegatePrefix, which means it has been proxied before. + if (className == nil || [className hasPrefix:kGULSceneDelegatePrefix]) { + return; + } + + NSString *classNameWithPrefix = [kGULSceneDelegatePrefix stringByAppendingString:className]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: %@", + className, newClassName); + return; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class sceneDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (sceneDelegateSubClass == Nil) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: Nil", + className); + return; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For scene:openURLContexts: + SEL openURLContextsSEL = @selector(scene:openURLContexts:); + [self proxyDestinationSelector:openURLContextsSEL + implementationsFromSourceSelector:openURLContextsSEL + fromClass:[GULSceneDelegateSwizzler class] + toClass:sceneDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(scene.delegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(scene.delegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(sceneDelegateSubClass)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create subclass of Scene Delegate, because the created subclass is not the " + @"same size. %@", + className); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return; + } + + // Make the newly created class to be the subclass of the real Scene Delegate class. + objc_registerClassPair(sceneDelegateSubClass); + if (object_setClass(scene.delegate, sceneDelegateSubClass)) { + GULLogDebug( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Successfully created Scene Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULSceneDelegateSwizzler correctSceneDelegateProxyKey]); + } +} + ++ (NSString *)correctSceneDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseSceneDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey; +} + +#endif // UISCENE_SUPPORTED + +@end diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h new file mode 100644 index 00000000..a2439eb3 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GULSceneDelegateSwizzler () + +#if UISCENE_SUPPORTED + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param scene The scene whose delegate needs to be isa swizzled. This should conform to the + * scene delegate protocol. + */ ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)); + +#endif // UISCENE_SUPPORTED + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h new file mode 100644 index 00000000..420b3e76 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !TARGET_OS_OSX +#import +#endif // !TARGET_OS_OSX + +#if ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000)) +#define UISCENE_SUPPORTED 1 +#endif + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULSceneDelegateInterceptorID; + +/** This class contains methods that isa swizzle the scene delegate. */ +@interface GULSceneDelegateSwizzler : NSProxy + +#if UISCENE_SUPPORTED + +/** Registers a scene delegate interceptor whose methods will be invoked as they're invoked on the + * original scene delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULSceneDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor: + (id)interceptor API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID + API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +#endif // UISCENE_SUPPORTED + +/** This method ensures that the original scene delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the scene delegate once). + * + * The method has no effect for extensions. + */ ++ (void)proxyOriginalSceneDelegate; + +/** Indicates whether scene delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if SceneDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isSceneDelegateProxyEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m new file mode 100644 index 00000000..47ac35d6 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -0,0 +1,213 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULUserDefaults.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSTimeInterval const kGULSynchronizeInterval = 1.0; + +static NSString *const kGULLogFormat = @"I-GUL%06ld"; + +static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]"; + +typedef NS_ENUM(NSInteger, GULUDMessageCode) { + GULUDMessageCodeInvalidKeyGet = 1, + GULUDMessageCodeInvalidKeySet = 2, + GULUDMessageCodeInvalidObjectSet = 3, + GULUDMessageCodeSynchronizeFailed = 4, +}; + +@interface GULUserDefaults () + +/// Equivalent to the suite name for NSUserDefaults. +@property(readonly) CFStringRef appNameRef; + +@property(atomic) BOOL isPreferenceFileExcluded; + +@end + +@implementation GULUserDefaults { + // The application name is the same with the suite name of the NSUserDefaults, and it is used for + // preferences. + CFStringRef _appNameRef; +} + ++ (GULUserDefaults *)standardUserDefaults { + static GULUserDefaults *standardUserDefaults; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[GULUserDefaults alloc] init]; + }); + return standardUserDefaults; +} + +- (instancetype)init { + return [self initWithSuiteName:nil]; +} + +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName { + self = [super init]; + + NSString *name = [suiteName copy]; + + if (self) { + // `kCFPreferencesCurrentApplication` maps to the same defaults database as + // `[NSUserDefaults standardUserDefaults]`. + _appNameRef = + name.length ? (__bridge_retained CFStringRef)name : kCFPreferencesCurrentApplication; + } + + return self; +} + +- (void)dealloc { + // If we're using a custom `_appNameRef` it needs to be released. If it's a constant, it shouldn't + // need to be released since we don't own it. + if (CFStringCompare(_appNameRef, kCFPreferencesCurrentApplication, 0) != kCFCompareEqualTo) { + CFRelease(_appNameRef); + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; +} + +- (nullable id)objectForKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(@"", NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet], + @"Cannot get object for invalid user default key."); + return nil; + } + return (__bridge_transfer id)CFPreferencesCopyAppValue((__bridge CFStringRef)key, _appNameRef); +} + +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet], + @"Cannot set object for invalid user default key."); + return; + } + if (!value) { + CFPreferencesSetAppValue((__bridge CFStringRef)key, NULL, _appNameRef); + [self scheduleSynchronize]; + return; + } + BOOL isAcceptableValue = + [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || + [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || + [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]]; + if (!isAcceptableValue) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet], + @"Cannot set invalid object to user defaults. Must be a string, number, array, " + @"dictionary, date, or data. Value: %@", + value); + return; + } + + CFPreferencesSetAppValue((__bridge CFStringRef)key, (__bridge CFStringRef)value, _appNameRef); + [self scheduleSynchronize]; +} + +- (void)removeObjectForKey:(NSString *)key { + [self setObject:nil forKey:key]; +} + +#pragma mark - Getters + +- (NSInteger)integerForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.integerValue; +} + +- (float)floatForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.floatValue; +} + +- (double)doubleForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.doubleValue; +} + +- (BOOL)boolForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.boolValue; +} + +- (nullable NSString *)stringForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +#pragma mark - Setters + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName { + [self setObject:@(integer) forKey:defaultName]; +} + +- (void)setFloat:(float)value forKey:(NSString *)defaultName { + [self setObject:@(value) forKey:defaultName]; +} + +- (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName { + [self setObject:@(doubleNumber) forKey:defaultName]; +} + +- (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName { + [self setObject:@(boolValue) forKey:defaultName]; +} + +#pragma mark - Save data + +- (void)synchronize { + if (!CFPreferencesAppSynchronize(_appNameRef)) { + GULLogError(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeSynchronizeFailed], + @"Cannot synchronize user defaults to disk"); + } +} + +#pragma mark - Private methods + +- (void)scheduleSynchronize { + // Synchronize data using a timer so that multiple set... calls can be coalesced under one + // synchronize. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; + // This method may be called on multiple queues (due to set... methods can be called on any queue) + // synchronize can be scheduled on different queues, so make sure that it does not crash. If this + // instance goes away, self will be released also, no one will retain it and the schedule won't be + // called. + [self performSelector:@selector(synchronize) withObject:nil afterDelay:kGULSynchronizeInterval]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 00000000..0d047818 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/GoogleUtilities/README.md b/MyExperiences copy/Pods/GoogleUtilities/README.md new file mode 100644 index 00000000..b04a2709 --- /dev/null +++ b/MyExperiences copy/Pods/GoogleUtilities/README.md @@ -0,0 +1,282 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-auth-badge]][gh-actions] + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-firebasepod-badge]][gh-actions] + [![Actions Status][gh-firestore-badge]][gh-actions] + [![Actions Status][gh-interop-badge]][gh-actions] + [![Actions Status][gh-messaging-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-symbolcollision-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains all Firebase iOS SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c6f1cbd/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/c13eda8/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/MyExperiences copy/Pods/Headers/Private/Firebase/Firebase.h b/MyExperiences copy/Pods/Headers/Private/Firebase/Firebase.h new file mode 120000 index 00000000..07ac6eb1 --- /dev/null +++ b/MyExperiences copy/Pods/Headers/Private/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/MyExperiences copy/Pods/Headers/Public/Firebase/Firebase.h b/MyExperiences copy/Pods/Headers/Public/Firebase/Firebase.h new file mode 120000 index 00000000..07ac6eb1 --- /dev/null +++ b/MyExperiences copy/Pods/Headers/Public/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/MyExperiences copy/Pods/Manifest.lock b/MyExperiences copy/Pods/Manifest.lock new file mode 100644 index 00000000..28c8297b --- /dev/null +++ b/MyExperiences copy/Pods/Manifest.lock @@ -0,0 +1,165 @@ +PODS: + - AppAuth (1.4.0): + - AppAuth/Core (= 1.4.0) + - AppAuth/ExternalUserAgent (= 1.4.0) + - AppAuth/Core (1.4.0) + - AppAuth/ExternalUserAgent (1.4.0) + - Firebase/Auth (6.27.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 6.6.0) + - Firebase/Core (6.27.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.6.1) + - Firebase/CoreOnly (6.27.0): + - FirebaseCore (= 6.8.0) + - Firebase/Database (6.27.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.3.0) + - Firebase/Storage (6.27.0): + - Firebase/CoreOnly + - FirebaseStorage (~> 3.7.0) + - FirebaseAnalytics (6.6.1): + - FirebaseCore (~> 6.8) + - FirebaseInstallations (~> 1.4) + - GoogleAppMeasurement (= 6.6.1) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 1.30905.0) + - FirebaseAuth (6.6.0): + - FirebaseCore (~> 6.8) + - GoogleUtilities/AppDelegateSwizzler (~> 6.5) + - GoogleUtilities/Environment (~> 6.5) + - GTMSessionFetcher/Core (~> 1.1) + - FirebaseCore (6.8.0): + - FirebaseCoreDiagnostics (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.4.0): + - GoogleDataTransportCCTSupport (~> 3.1) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 1.30905.0) + - FirebaseDatabase (6.3.0): + - FirebaseCore (~> 6.8) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.4.0): + - FirebaseCore (~> 6.8) + - GoogleUtilities/Environment (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.6) + - PromisesObjC (~> 1.2) + - FirebaseStorage (3.7.0): + - FirebaseCore (~> 6.8) + - GTMSessionFetcher/Core (~> 1.1) + - FirebaseUI/Auth (8.4.2): + - Firebase/Auth (~> 6.0) + - GoogleUtilities/UserDefaults + - FirebaseUI/Google (8.4.2): + - FirebaseUI/Auth + - GoogleSignIn (~> 5.0) + - GoogleAppMeasurement (6.6.1): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (~> 1.30905.0) + - GoogleDataTransport (6.2.1) + - GoogleDataTransportCCTSupport (3.2.0): + - GoogleDataTransport (~> 6.1) + - nanopb (~> 1.30905.0) + - GoogleSignIn (5.0.2): + - AppAuth (~> 1.2) + - GTMAppAuth (~> 1.0) + - GTMSessionFetcher/Core (~> 1.1) + - GoogleUtilities/AppDelegateSwizzler (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.6.0): + - PromisesObjC (~> 1.2) + - GoogleUtilities/Logger (6.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.6.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.6.0)" + - GoogleUtilities/Reachability (6.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.6.0): + - GoogleUtilities/Logger + - GTMAppAuth (1.0.0): + - AppAuth/Core (~> 1.0) + - GTMSessionFetcher (~> 1.1) + - GTMSessionFetcher (1.4.0): + - GTMSessionFetcher/Full (= 1.4.0) + - GTMSessionFetcher/Core (1.4.0) + - GTMSessionFetcher/Full (1.4.0): + - GTMSessionFetcher/Core (= 1.4.0) + - leveldb-library (1.22) + - nanopb (1.30905.0): + - nanopb/decode (= 1.30905.0) + - nanopb/encode (= 1.30905.0) + - nanopb/decode (1.30905.0) + - nanopb/encode (1.30905.0) + - PromisesObjC (1.2.9) + +DEPENDENCIES: + - Firebase/Auth + - Firebase/Core + - Firebase/Database + - Firebase/Storage + - FirebaseUI/Google + - GoogleSignIn + +SPEC REPOS: + trunk: + - AppAuth + - Firebase + - FirebaseAnalytics + - FirebaseAuth + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseDatabase + - FirebaseInstallations + - FirebaseStorage + - FirebaseUI + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7 + Firebase: fc4cbf6f1592636431821ef9a3c557e4dfd9f268 + FirebaseAnalytics: 0ea640473474f036cabbc2576e20c2d63671c92f + FirebaseAuth: b85c064e0ac60f82486728d50a4803f235687302 + FirebaseCore: feda061cb1ee6d8ad4824f4a4a8ffbcfe284f595 + FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84 + FirebaseDatabase: 3d02ffa794ec174853c086cf87cf2dc79bd6da49 + FirebaseInstallations: 293f567159b6d66d1c990f13bb868066096c94ec + FirebaseStorage: af7bdbd12177cf567df00904e3e3a93704f25b15 + FirebaseUI: e57e9b9c4340631151fbe67a14206d23d0974f37 + GoogleAppMeasurement: 2fd5c5a56c069db635c8e7b92d4809a9591d0a69 + GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 + GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d + GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213 + GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 + GTMAppAuth: 4deac854479704f348309e7b66189e604cf5e01e + GTMSessionFetcher: 6f5c8abbab8a9bce4bb3f057e317728ec6182b10 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 + PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75 + +PODFILE CHECKSUM: 4195f04b27b7f552f1bacbf30465a5eb43adf594 + +COCOAPODS: 1.9.3 diff --git a/MyExperiences copy/Pods/Pods.xcodeproj/project.pbxproj b/MyExperiences copy/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2e546a9c --- /dev/null +++ b/MyExperiences copy/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,9663 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXAggregateTarget section */ + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */ = { + isa = PBXAggregateTarget; + buildConfigurationList = F9BC9C68ACBBE046A8A6911ECF5B862B /* Build configuration list for PBXAggregateTarget "Firebase" */; + buildPhases = ( + ); + dependencies = ( + D99C37BE936E12B58FC32858233436EE /* PBXTargetDependency */, + A5945ED690D018F5F3BAC40EB80112D1 /* PBXTargetDependency */, + D35079C7BFFC9D393376AB8428F319E0 /* PBXTargetDependency */, + 955C99E32D560318496D3EE66A0FCC85 /* PBXTargetDependency */, + DA37C675CB443F217AF335EC7B4EC00D /* PBXTargetDependency */, + ); + name = Firebase; + }; + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 311E5E7F5B7EA3517988E8CC09918B82 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */; + buildPhases = ( + ); + dependencies = ( + 061C01B3BE32CDA65FF174894B84F457 /* PBXTargetDependency */, + 8F31BBD06489C0BE8183A7B761920DBD /* PBXTargetDependency */, + ); + name = GoogleAppMeasurement; + }; + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = FF8A00C0999DC87832BE4C932BDF83FF /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */; + buildPhases = ( + ); + dependencies = ( + 2C0EC82F9C670F1DC5657EFD705B724C /* PBXTargetDependency */, + BFFA99EB13B6A8F396C04EC1A6450BEF /* PBXTargetDependency */, + 27917D894565B334081F9B17D91FD3B6 /* PBXTargetDependency */, + FE7A852F0E43A74DD415897DD5E4BDC2 /* PBXTargetDependency */, + F010753889728A35377801C8F15D17A9 /* PBXTargetDependency */, + ); + name = FirebaseAnalytics; + }; + CAD3534FC55B0333104E5117C0A9A324 /* GoogleSignIn */ = { + isa = PBXAggregateTarget; + buildConfigurationList = EF506430F7C768387213C9554EC30E56 /* Build configuration list for PBXAggregateTarget "GoogleSignIn" */; + buildPhases = ( + ); + dependencies = ( + 4466D3DE2D8BB2D0953C98C7431C668D /* PBXTargetDependency */, + 1FAA13BA586F7B8D714A0FC57EDBA63D /* PBXTargetDependency */, + 2B20806AD06B7E23F12FFA35C1265843 /* PBXTargetDependency */, + ); + name = GoogleSignIn; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 00197BF6C4501557C3BC99B81DFAC0FD /* FLevelDBStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3D34F30D5AC628C0E88C3FDE526588 /* FLevelDBStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 003BC15B01B115BE46E8FAA7DB3315FA /* FIRSecureTokenResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 9116AE55C96DD4B7CC8A610D2763F4CC /* FIRSecureTokenResponse.m */; }; + 009E758800055F3BAADF302919166AFD /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8D7D0BBB9B7971147224F4CC49B258 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 00CC75B60414D7910BCC30EE254B618D /* FIRStorageReference.h in Headers */ = {isa = PBXBuildFile; fileRef = D79C916C4A7F1CD706F33D10361AD2A1 /* FIRStorageReference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00DADBF26BEF6BD179AE093EC9231CCC /* GDTCORTransport_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 84B8016FA7491959E6CEBA3C1A3E0E22 /* GDTCORTransport_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 00DEDBFB7AC7FD5602601B725215FBC4 /* en-AU.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 46537E48C5450772F4B264F790FD1694 /* en-AU.lproj */; }; + 01322E8416BAA0FBAD9488F437562DA4 /* gsw.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1A7A8CD6C8BB3A13F9B114C37E9FEAC4 /* gsw.lproj */; }; + 013D945A6EB50B6FC9854DE84D18E44A /* OIDAuthorizationService+IOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 3739C5F655F31DED05B46617ABCB9412 /* OIDAuthorizationService+IOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 01561D513FCA73D5A6E6AB77DA1FA9A6 /* FIRStartMFASignInResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C544C318DE1B07A1D697B0F86F8E333 /* FIRStartMFASignInResponse.m */; }; + 0200AA2050195591B45B63AC85881913 /* AppAuth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 249F2A82CBC0749A828D61764B441E28 /* AppAuth.framework */; }; + 0239049C823CE542E12326468AE9EDCC /* FBLPromise+Recover.m in Sources */ = {isa = PBXBuildFile; fileRef = A67AFCD9FDFD86A36567F4CA75A18EDD /* FBLPromise+Recover.m */; }; + 023B762A93BB97ECA95535A6A05D9518 /* ro.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 190DF118BCA465ED356FCBBE1176A561 /* ro.lproj */; }; + 025F620E8DE6EED3B6624A89A7B14B0A /* nn-NO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 20EABA71D9A42FBE54F15ED4D7A36D2C /* nn-NO.lproj */; }; + 02780B28FD6A9973F8CE67A844991646 /* FEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 847467AF5025D6B485DB432C7B7581C2 /* FEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 028073448A6EB2523EB06EEED522C673 /* FIRInstallationsIDController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BA768461B023567D35A1231C542EC87 /* FIRInstallationsIDController.m */; }; + 0284D4732B1E2B5E8B7344503C1B1EB9 /* table.h in Headers */ = {isa = PBXBuildFile; fileRef = F59468EA40FA729BFE3CD9A8006CFBEE /* table.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 02CCB32F8551290FA005E433C496610E /* es-BO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 26FF61F5D948E7FB9711D97EEA148219 /* es-BO.lproj */; }; + 02F5B13714B874C3002AB1F5F208220B /* sr-Latn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 8458CF3753249A59F6F220A43276CADE /* sr-Latn.lproj */; }; + 031341098166167255F538ED1609FACE /* FTupleNodePath.m in Sources */ = {isa = PBXBuildFile; fileRef = D06BB08F59112DF40E024F3DCB8BA877 /* FTupleNodePath.m */; }; + 031A9D77AA65D0809D6C706089207682 /* FUIPrivacyAndTermsOfServiceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 26EB1333BCF8E07CE70BEC92753A775C /* FUIPrivacyAndTermsOfServiceView.m */; }; + 03AACEA13BDE64E5A5B1E7B73CB7A91A /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = EB2E6210777537A1E815E5BB3432D4CF /* FIRComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 03ABC297C208C94A6AC41284AA1A6931 /* sr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C9865EBDD0EB8C79D569F548638FCC3D /* sr.lproj */; }; + 03AC71BC9F79E188BC0E854CAE4F73DE /* FIRVerifyClientRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CE72AB024AB58E38E7CAAC21CEFD758A /* FIRVerifyClientRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 040398E7E9AB077D7DCBF6E45442DC68 /* FAckUserWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = DE3C6C8B7895242C8B7E1A4EF84D3273 /* FAckUserWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0425D372E9746ABAC18FFA2886EE6534 /* FEventRaiser.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CD80825846CFECCE10B535583137409 /* FEventRaiser.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 046BDDC81155DF76DD41278878DD2903 /* de-CH.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 99BF294419A82872B273C32B3313AD54 /* de-CH.lproj */; }; + 047249349DA6FD3DAE63565A26BF17E5 /* nanopb-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B7EBBBA5B262CA6C018FC09D4BDA7CBD /* nanopb-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 04B651F8B783B4C6904C66FA80945853 /* testharness.cc in Sources */ = {isa = PBXBuildFile; fileRef = FB67B500FD9B4600EC2F304EFDA38590 /* testharness.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 04E1AA6153D8E934692804A01982FB01 /* FIRGetAccountInfoRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BFD29E8171D39915525EB07724F0AEB /* FIRGetAccountInfoRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 051C35E3F0AFBC2B0DFD4BD20953603C /* FTupleFirebase.h in Headers */ = {isa = PBXBuildFile; fileRef = 6365C0AF9225C127A860B57949F71079 /* FTupleFirebase.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 055488955277E0E9136A6DFE4651B9AA /* FIRWithdrawMFARequest.m in Sources */ = {isa = PBXBuildFile; fileRef = AC61C5ABD2CCCABB38B49666D763500D /* FIRWithdrawMFARequest.m */; }; + 055AB0BE1C4FCB9657F634D36CEAC98E /* FIRGetProjectConfigResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FC0EA04586CCBCCD2808FC6B7762C4C0 /* FIRGetProjectConfigResponse.m */; }; + 056AFC1435644485EAE1B012749CF09C /* FBLPromise+Async.m in Sources */ = {isa = PBXBuildFile; fileRef = 46A8D09E3ABE20DB3AF5BCBC70C770B6 /* FBLPromise+Async.m */; }; + 056E8F8BDDB1AFF2FBEFE7F93112B495 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A25A30BCAF35ADC592EE18444941D9 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 05E9C86C4FD988F2A4DCBE94344E534F /* table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 674D53C4BF02A9ACA05F1A27000C5EF7 /* table.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 06283E1D781D85AE9430AD9F1AAE3615 /* FIRWithdrawMFAResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 7853F03B091136CF9515F12807177703 /* FIRWithdrawMFAResponse.m */; }; + 0635DC0B0F4725383E83C0427634E26E /* GULAppDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = D1B62426B683A0486229605D8AF442B2 /* GULAppDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 067099545B3490DB37E9CE7ADB97E22D /* FBLPromise+Testing.h in Headers */ = {isa = PBXBuildFile; fileRef = 818E56D83F281D68C11461EBA7312C1E /* FBLPromise+Testing.h */; }; + 0670F9B0D4BA8C54C8A23C22D9E5618E /* FIRStorageGetMetadataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 02A0E580086D035BB4EC4EFA878CAC1D /* FIRStorageGetMetadataTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 06953BA616880F876D31CECCEDC11105 /* OIDAuthState.m in Sources */ = {isa = PBXBuildFile; fileRef = 0992AED4D85D10AED6036ECFCAAF7207 /* OIDAuthState.m */; }; + 06B3FD4869C8C25A4501C123A0FBE7B4 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = BDB88ED4C4E94AA853AEA687BD141AC8 /* FIRLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 06EBA32B60BA67EE31AE3D2D4A6D8B9E /* FIRVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 275B5FDAECAB2575C5E82DA5E44D88CD /* FIRVersion.m */; }; + 075E34225D4CE71C2F2FC63FB9CE0CA3 /* OIDAuthorizationResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 008F4820544BC65FA5681C6A4E10A41A /* OIDAuthorizationResponse.m */; }; + 077CE3975A409D2CCB2066EF790A2560 /* FUIAuthPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88D1A747FD5261ACFF61437E691C185B /* FUIAuthPickerViewController.xib */; }; + 07D305CA86236684A8B7DB7A9CF976D5 /* FSnapshotHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FE49F161741365656721C78D4163690 /* FSnapshotHolder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 07FFFE781397273584461E3DF9FC7E7B /* FIRErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B851A17E68A633AC605EF3F4D6C2A38 /* FIRErrors.m */; }; + 0816CC9A4E6FAB0F54D1769AFAF40689 /* FUIAuthTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4730405FFEC430182522451A957E885E /* FUIAuthTableViewCell.m */; }; + 082620B4CAFF07381D466C7F54CDC435 /* OIDAuthStateChangeDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 052053BBDBFA807842AEFBCF43F360FB /* OIDAuthStateChangeDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 08784F7E5048AF41B6948FC917F3E652 /* FIRStorageDeleteTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C1B95C2C3697B27A7E6D35B1471E75 /* FIRStorageDeleteTask.m */; }; + 08B1AA1DA2B95D9ABEB2E5E7F756BCBF /* vi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BE2D05806F5FFBEDF2E3296B2922BC7B /* vi.lproj */; }; + 091E5416619836F280790E6F7FF6A8E1 /* FIRAuthInterop.h in Headers */ = {isa = PBXBuildFile; fileRef = CDB74299006EB164009D493442C606F5 /* FIRAuthInterop.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 09368BC6AE4BB0DD312FFE6C47FAD4D7 /* NSData+FIRBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = 08E72A8C52BAD62FEB94490A1F2BF9B8 /* NSData+FIRBase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 09AD282B1DD0537B45C2B752EBF5B09B /* FIRSignInWithGameCenterRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC1393DC856702660ACD7A0599DBD56 /* FIRSignInWithGameCenterRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 09BA60872EA3FB0F04659071ED913C62 /* mr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4195822B54AB8FA1BEA64F7C1983BAB7 /* mr.lproj */; }; + 0A293264F3505A12229B2D28EEF9CCF2 /* ic_account_circle2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 80555E26FEBB765547F06A92F10BBFAC /* ic_account_circle2x.png */; }; + 0A3B29ABFB794000DB38123C64FDE483 /* FIRInstallationsItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 76F71A018847DEC561975C4EADA9A9F6 /* FIRInstallationsItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0A73B6F3F5E2B453AEF9F687C7D2AC63 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F70E4BE2CF979D01CD0A2A2CC576453 /* FIRLibrary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0A76A49CAD54FC8D7B15344AD19A3CF4 /* de-AT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 04FD97AE67C10679D659B68EFCB64697 /* de-AT.lproj */; }; + 0A828513A4E67FA6621CB3672B9B93FE /* GULMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = D3C1B3F5110E2256AB2C545D67205C5F /* GULMutableDictionary.m */; }; + 0A83C33151A74978B5009466B16AA320 /* OIDExternalUserAgentCatalyst.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C90E3FDA5545E6FD31403207BF27DC /* OIDExternalUserAgentCatalyst.m */; }; + 0AE9F9F29EB3BB9798F860FDDE3CD3ED /* GDTCORPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 89891420777E264E545EE3102D324C80 /* GDTCORPrioritizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B55923174EC0606AF685E473C363866 /* FIRAdditionalUserInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 900D7AA1AF5F2CCCFEC7B2A6D7F92D3B /* FIRAdditionalUserInfo.m */; }; + 0B594E286853A9821C2EAF9FEDF2CF6D /* FEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = C2108C3AC4A847D23C1CED0BA5C0EC93 /* FEmptyNode.m */; }; + 0B764CD79758A19F877947F521050A30 /* OIDTokenUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C387865C9997476DD5F58576360815E /* OIDTokenUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0B9EFEF5F16CC638C800D057AE1B46AE /* FIRAuthStoredUserManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B0FA2F0A3D5C566608F18B383B6CF044 /* FIRAuthStoredUserManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0BB7F3F84BFBD9CF5163A448BA3F76C7 /* FIRAuthTokenResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 48BCA366BED224540BBF9225961D5874 /* FIRAuthTokenResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0BF2D63AE4359403053AABC24581FAFD /* FNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ECDE361BF011270F99FEB1A9A3B6FE9 /* FNodeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0C35999BF6A9FBF3D42A76F1C4D3BDCD /* FBLPromisePrivate.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 823FF738D2EDB86AD387E9C9A0628A1F /* FBLPromisePrivate.h */; }; + 0C4B659CE577650B21A2666B18E1A730 /* FChildEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = D26F148081403A34009C3E64571BB81E /* FChildEventRegistration.m */; }; + 0C86E322017FB0EE41297323FA93E83A /* ic_google@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 17A216C406500454DF05929B98E58410 /* ic_google@2x.png */; }; + 0D07435B8AFFBE4E95D235E7B731BB79 /* FIRBundleUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 058B86FB42735EFF6012341A73CFD1FF /* FIRBundleUtil.m */; }; + 0D0C12C3AD18431E78E060F6179AA9C8 /* FIREmailAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = FFE5D5FAFCA8CD85996CACEF15BA5467 /* FIREmailAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0D69C1B4514D9905D23344A8BEB49CE9 /* FIRDependency.m in Sources */ = {isa = PBXBuildFile; fileRef = D7FBF775D2A98B0943509C6C0492F77D /* FIRDependency.m */; }; + 0DFCF05C003440CA970EB17DD6C48806 /* FViewProcessorResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 118374FE49AD27D512B8BA9E44E4B3EB /* FViewProcessorResult.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E05314112A4239F98622C4830F4A269 /* FTupleOnDisconnect.m in Sources */ = {isa = PBXBuildFile; fileRef = 10414BB146383FB69BFD1324CB140BD4 /* FTupleOnDisconnect.m */; }; + 0E139B6013FF88D7B2841A9919E24AE5 /* GDTCORUploadCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 303AEFF4641C47112E439DB5513D8778 /* GDTCORUploadCoordinator.m */; }; + 0E23750FE124E07AFF21DB9AC9542BCE /* AppAuth-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA19D221880B1D318DD890057CEBF1F3 /* AppAuth-dummy.m */; }; + 0E2A523C16DD8DFFC23E95AE5A7396B9 /* FIRAnalyticsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 96164D8ACC099570AEFE2AD13C866D21 /* FIRAnalyticsConfiguration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E3FC676750F1FCE239C087EB2E6D8F2 /* FMaxNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E2A358A42E48E791E99164F4A01D034F /* FMaxNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E73740CE03CFFBCF2553BBD03C8709C /* posix_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 402DDDB7F31C1C5CE3C227D44A4DECCC /* posix_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0ECA3281C3E76B71D71D1EE9395293AF /* FIRDeleteAccountResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BEBBED032A65D6D7E7177E7EBD6307E /* FIRDeleteAccountResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0EE0173B606FDC763F1A14EBCEBB0033 /* FIREmailLinkSignInResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 24A6A8B562A7BB27357C8B086C0E3880 /* FIREmailLinkSignInResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0EE4A6689AA07EA982A2957C64FA95F9 /* en-SG.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A6A2A48DDBA7CD20E2D170FF98D7D6E2 /* en-SG.lproj */; }; + 0F2500D0441CC03A2598B059E068660D /* APLevelDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 12687F38DDA65406B56C297FA9B2EE9B /* APLevelDB.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0F32EAB908DFC8FDE2D3B714A40953AE /* FirebaseCoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F44E5B36FA5106930486C4FA63C17B /* FirebaseCoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0F49128C205AF2A2509D53D5579911DF /* filename.h in Headers */ = {isa = PBXBuildFile; fileRef = 670E3A3782427E916EB9BB0D0B681559 /* filename.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0F55EFE4975D747D5AD40940BC84C5F9 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 180C6EA8C3894CB86B604C1AAA40521F /* FIRLibrary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0F75CE6137488B705DCF5D0FE9D18D98 /* filter_block.h in Headers */ = {isa = PBXBuildFile; fileRef = 48914A7BA911F9F5780304712CAA8770 /* filter_block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0F837C468B671045AF6922BC1AE34A17 /* hr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 6EA549DC6A9769196F50FEAAFE6F9D2E /* hr.lproj */; }; + 0F90AFD30D19FA2F88C502EECE262BBF /* FRangeMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = 1405A82BE0B36A65A6E5B9FA9BBECE56 /* FRangeMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0FCB629DA14579BACECA832EAF9B659B /* ic_visibility_off@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7CA87D9C42EE5FB93F71C78E42F2D2EF /* ic_visibility_off@3x.png */; }; + 103EE4551AC02CF6FB95F308BFA33FD6 /* FIRTwitterAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 00DECA92B7EE6396FB998E278B411EB9 /* FIRTwitterAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 10606B75F34F9D4BA3F0CB6926EE1A2A /* FIRAuthDataResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 6148070EDD3BDC2C008E97051E5E51CB /* FIRAuthDataResult.m */; }; + 1080C7CBAF82E3C295D3F7EBA0CC6A92 /* es-NI.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 76A00F380F7CB86BC5ABAB18B8C3C512 /* es-NI.lproj */; }; + 10BDEE9B0C9281E76BB1078DD2BD5796 /* FUIAccountSettingsOperationUpdatePassword.h in Headers */ = {isa = PBXBuildFile; fileRef = CC5FC2B13E49CF3005150C72BB9FAA4F /* FUIAccountSettingsOperationUpdatePassword.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 10D6FD725A3B8210C27EB011330862F7 /* FBLPromise+Delay.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 3CAEE40E2A06A4534FC90D028269EEAE /* FBLPromise+Delay.h */; }; + 11EA9C12F47BE1E080C68147850FBF65 /* lv.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1F7DC439F0D2B26FCAA3BB600B86D9A7 /* lv.lproj */; }; + 1202EF6BAEF6D33CE6C057BA2911D3BE /* GULSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = BDEC68EAE51158E1F4BB5115466D6247 /* GULSwizzler.m */; }; + 120CD82B71E3E547CF68417454F0DB5B /* FIRVerifyPasswordRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E7D49DB2F3223117BA44B91C6B9E48A /* FIRVerifyPasswordRequest.m */; }; + 1226E8980CFB9C8990AD557278EA99B8 /* ru.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 03C4883C10FF5038DF368CDEDE4218B7 /* ru.lproj */; }; + 125AD7E43E40469ACF1CD61FE87C2C85 /* en-IE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B0CC498F1F77BEE204AA9B103D245937 /* en-IE.lproj */; }; + 1263598C5A64B4D36FEB0C0393F17CBE /* FIRMultiFactorSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 78AB14E26E13BE6E71FA466FD1F7C0FC /* FIRMultiFactorSession.m */; }; + 12F05C34BFA2A9B171512D29F3657F43 /* GULAppEnvironmentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F2E84C3E82B88B41FC14399D96AFF7E /* GULAppEnvironmentUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 138B814247C78F12A672FBEE055D7827 /* FIRStorageUploadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = EC03F375BA39952863BFCD4DE1C9BCD3 /* FIRStorageUploadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 138EB885AE9B8EC5EF961BE4CB222E2F /* FirebaseCoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6354B7053086BB30B515EDE313EB0572 /* FirebaseCoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 13FCD80568E9B4AD339C79EDED4BA2FB /* FBLPromise+Race.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEB318E95935B837B5592E7BE729383 /* FBLPromise+Race.m */; }; + 14F2303E429FE24F27D5DDABA686B3EB /* GULNetworkMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7AF946105D40415BEE2B4C29262A5D /* GULNetworkMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1507F4EFA5216031D5CF868136A835C1 /* FIRInstallationsAuthTokenResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEEFBDAF3FAAECFB109E6E0B60D19DB /* FIRInstallationsAuthTokenResult.m */; }; + 15190280A7464589E58C69A821873970 /* FUIAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = C7797DEC71A199778D2E303EE512CA30 /* FUIAuth.m */; }; + 151C90C5A2D4B8809BFB331B2ECFC28B /* FIRSignUpNewUserResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 00AC724E951A64118AD7189A15610DE6 /* FIRSignUpNewUserResponse.m */; }; + 152481DAFF8FA47F61BB412784DF31E9 /* OIDAuthState+IOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C160DA81101F1D0015E334D29C329E /* OIDAuthState+IOS.m */; }; + 1547776673C1A743D3AD20732D62FB04 /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = 3973CC931936DEF986B63B91514EEE6A /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 156146F448852ADD9C9D3B49860DF567 /* FIRInstallationsHTTPError.h in Headers */ = {isa = PBXBuildFile; fileRef = E94487BBAAF18F4F350804E397EF0748 /* FIRInstallationsHTTPError.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 15BC580532B984757EF912439B2D3DDE /* FBLPromise+Any.m in Sources */ = {isa = PBXBuildFile; fileRef = 5404F30E0CBEEC5274DCB96F2A740A85 /* FBLPromise+Any.m */; }; + 15F5C8C87F63A3D89CA54F07930CF0BB /* FIRAuthKeychainServices.h in Headers */ = {isa = PBXBuildFile; fileRef = 9003091EE6B741989C260584A1A67492 /* FIRAuthKeychainServices.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 164984C1769476DC3C01516D23ED4AEB /* FIRAdditionalUserInfo_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 44D2EDB1270B1F582810B370AB8F2F1A /* FIRAdditionalUserInfo_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 16543FBCEE63DF8AE41E9AFB0D3B7D6D /* FBLPromise+Timeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 50BD34FADDD845EBC8222D9EB3995F05 /* FBLPromise+Timeout.h */; }; + 169A74523986554B514943622050DBE3 /* FIRInstallationsErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = A251FCAE5F4EAAEB842779316E4F5C02 /* FIRInstallationsErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 16C1AA8A28F90B8F5AE061BEA96D8BB5 /* GTMSessionFetcherService.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B7DE22D7576368040FBF615532A0DA3 /* GTMSessionFetcherService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 16F96D0B2EE7EBED059FF327B8E90E5E /* OIDClientMetadataParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 01A4C1808C82E6CD358A94DB8090721E /* OIDClientMetadataParameters.m */; }; + 1702515A00A41042474A777753CE700E /* FIRFacebookAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C06F2CB64F40C1BEFC844D191BCED3C /* FIRFacebookAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 170FA1BE2AFDCE0B8CF8562A7993E260 /* FIRFinalizeMFASignInResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C08645CF610E0A55FA7C8135E3E4B04 /* FIRFinalizeMFASignInResponse.m */; }; + 171B588DB4215B73A93382C9B2534702 /* iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 78E779BCE9ACE526BBCA1D359975D546 /* iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 17587A84F44BB3F9BBE44E3F0BF91929 /* OIDScopeUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 6189375E4157BB1E09D2728778079CC1 /* OIDScopeUtilities.m */; }; + 17993EED5265C3BF7DC731E399AA339F /* FIRTwitterAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F9164B27690D519BFFCC086D81CFFD /* FIRTwitterAuthProvider.m */; }; + 17B79354012E32ABDE229A9C9EC52402 /* FUIAuthErrorUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 9965D14C5646EB689F1143289D36CDB5 /* FUIAuthErrorUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17D33ABE5E7B27EADA2DA3D0543D9D17 /* FIRDataEventType.h in Headers */ = {isa = PBXBuildFile; fileRef = 706EA4C9C7E61F24F7B8DDB2437C8F9C /* FIRDataEventType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17FEFA87927228952E256731494E9ACD /* gsw.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 160F9D533A4A53571BA6D1E2172D1F0C /* gsw.lproj */; }; + 182F4AA1B9CECAA997F15A9F092F1B90 /* hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = 855CE6FFCB03AA76B086DD233B1F03BE /* hash.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1833D1267C3EA07F8D14FDC36F170E7B /* log_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BBAD787550D738C9C7AC6091D67E8E4 /* log_writer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 185224D6AC8CBA6755BFF836EF98AD1E /* FIRAuthURLPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = D9E223315FB9AADC49B259DD2B5AF5BF /* FIRAuthURLPresenter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 18D63BE1F3E713E003C5268ED2A02BBB /* FBLPromise+Await.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B219104CD42208B88312DE148CB3A0 /* FBLPromise+Await.h */; }; + 196265062E4E5B2D9F3915B6CA0B545A /* FIRAuthErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = AECF8D6DA7C8A464989CB066D473F472 /* FIRAuthErrorUtils.m */; }; + 196CFC01D9D935E653A494A4E29C268B /* FUIInputTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0C87CCE8B50E854B57AD5AA483FAA4A /* FUIInputTableViewCell.xib */; }; + 19A227E1CDBB9C68968FE8A81AA08FB2 /* merger.cc in Sources */ = {isa = PBXBuildFile; fileRef = ECB5A800627C88957FA98B1987378A64 /* merger.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1A1EF49485D4256AE152524C1FB5DEA4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 1A433A2C2D1A8EE0107949AAC343B9DF /* ru.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F12D465A15972386FC714191DB492F6C /* ru.lproj */; }; + 1AA52F54BD216582909D04A084F42C1B /* bg.lproj in Resources */ = {isa = PBXBuildFile; fileRef = FACDEAFE27619DEF3D9C6BEBD477202C /* bg.lproj */; }; + 1AF7C66EF8BE31F36E7D744D5832297F /* FWriteRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = B2C1368FD864972A677AA6F00D203E6D /* FWriteRecord.m */; }; + 1B1043A3469C9CCD275480C414D650F5 /* GULSceneDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 42C7BFFB0E3DE1C0DDD9CA158FDDF6D6 /* GULSceneDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1B2359FB213D972B04AB428B73428914 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FA08E7E33E3A732A355057DBAD35E45 /* FIRComponent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1B584D4EA6BA6603F3B982BDCD7DF8C5 /* FIRAuthWebUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F19532C1B98CB916ADC4049AD0646E /* FIRAuthWebUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1B73E81673E7E238C00501CE8B0A90F1 /* block.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2933987BB6A2053504823F17604CAFE /* block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1B8EE3F7B7617A196DDD1723A10149E7 /* FBLPromise+Reduce.h in Headers */ = {isa = PBXBuildFile; fileRef = DE3965AFA52554A33633B6C0264AAFB7 /* FBLPromise+Reduce.h */; }; + 1B9467E56F5AC87A6DC43329E42DE40A /* sk.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 01DB54993FD7E077C1A2FDA6680AD562 /* sk.lproj */; }; + 1B9F33FCAC1A035AC50F41584DE984F0 /* FUIStaticContentTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34194FA899C7983A97CFA1667E3666D9 /* FUIStaticContentTableViewController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1BC76176733CDE9A8DCF1E94651A2C6A /* FirebaseCore-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E258FDF1B764B343037CC2895777F91 /* FirebaseCore-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1BCB007B654E839010C95526E541AE01 /* FBLPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = A069F158CEFBA4E38C45563122AFCC5F /* FBLPromise.m */; }; + 1BED475252F19F56DAA42787AF60BDF5 /* FIRDeleteAccountRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 757AFA09EEDF7E69BA225B0049AE4C79 /* FIRDeleteAccountRequest.m */; }; + 1BFEB4DCECE73B7242A3D7797C26F084 /* FIRMultiFactorAssertion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F2114000F4B4E452E61D687C2422EB2 /* FIRMultiFactorAssertion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1C4ED94042C78A1CF1B53357D7FC2495 /* ic_visibility_off.png in Resources */ = {isa = PBXBuildFile; fileRef = 4376CE82EF1BF0ECFA794D85F3766F87 /* ic_visibility_off.png */; }; + 1C6558A6591DAB25C5A28AA82F25091E /* FTuplePathValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4383A93D64CCC99B231FE7ECB7CB0C6B /* FTuplePathValue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1D15786A3973F469C0E325EAD86AB1D1 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 7235427A1267E29C913763C2DD9508AF /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.m */; }; + 1D583754AB5ECEDB63D697A28FCD900D /* FBLPromise+Validate.m in Sources */ = {isa = PBXBuildFile; fileRef = 349D453606D972CC4125A9235D6AEFEA /* FBLPromise+Validate.m */; }; + 1D7F88A99C8741A43BC0CF686E43F0B0 /* FIREmailPasswordAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 31FEC4E1D3426CA59F02F81AF0A49EC6 /* FIREmailPasswordAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1DB9E2F55C23697926E3C5BB9FE37DD5 /* FUIAccountSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18E84252C8BBFC1F7C570CCCEA4B789D /* FUIAccountSettingsViewController.m */; }; + 1DFADAB105B05EDC592E3C8FE565F8D6 /* FTupleUserCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = EC9A2EB346797982B9ADD669A3C48AF8 /* FTupleUserCallback.m */; }; + 1E4AE3B73C726FDA0246496E600A5BC5 /* FIRAuthErrorUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = F26BE0CF90BD08FB506A58DF1E66DFAC /* FIRAuthErrorUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1E6036CD752AD8FA051D55F790802066 /* FUIStaticContentTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A7950EBD3C0C73CAF6F2AECCB1F0F04E /* FUIStaticContentTableViewController.xib */; }; + 1EF66BB9A24839176E1B2E8ACF2E9B66 /* FBLPromise+Then.h in Headers */ = {isa = PBXBuildFile; fileRef = 925C41F8B9D85ABE6F2C5D11D6784234 /* FBLPromise+Then.h */; }; + 1EFC1611BD2CE88883B5E2AC40C2EF79 /* ca.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0098C77A2AF070A9DED76E3055458A8C /* ca.lproj */; }; + 1F53CCD14D2A736AAF3B0F4194A03721 /* nanopb-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F6B023A8F096B22FC186C9C8E59C42A /* nanopb-dummy.m */; }; + 1F5DDD087484ABCEE446AECCB63EE7B2 /* FIRGitHubAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBCAC752D4D966314C7ED6C79EF83E9 /* FIRGitHubAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F7474582F6339605964C52104366D3B /* FIRAuthSerialTaskQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D3C88BA14651AAF531A1534E6274A7D /* FIRAuthSerialTaskQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1F99D3CB1E0A313C9973622AAC67C5D8 /* FIRStorageListResult_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B88E94C33408BA3A4273682782F14A5 /* FIRStorageListResult_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1FAC0F4A21BC91C15C9CD4BE844BC869 /* FPruneForest.m in Sources */ = {isa = PBXBuildFile; fileRef = FF680DFC00216365C48B4199252AEB01 /* FPruneForest.m */; }; + 1FAE22850E5DFA7BCCA885C8C5FB73BC /* es.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 5E2CA4028042B0790AE59AB6B90E6E8C /* es.lproj */; }; + 201D67C516A0D11EC1DE4AB438669F15 /* FTupleCallbackStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = AF4EA4512BEB4222E9BFDDF30A07AC8D /* FTupleCallbackStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2033ABD8D11A8F188CB1D5A7C28B8C9C /* FIRAuthDefaultUIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3002482FBBE4FC29A381308810AAFA04 /* FIRAuthDefaultUIDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 20399816554993CB9A054CB009CC89A1 /* FUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = B85875DD11E278FBC02338C96C934B34 /* FUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2095003DC22D3D86A334AA1A1561900D /* OIDErrorUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EF13F13E0C7FAD491A17E36510E58B5 /* OIDErrorUtilities.m */; }; + 20C8FD2B3651B68D732BB7CA4591E51D /* FIRAuthCredential_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C4A684387AAD595A79267AB8478CC2 /* FIRAuthCredential_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 20D706725AB113719E24B9D3D1A85956 /* FIRUserMetadata_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = A6A6CEC85A5CC5B5C02A3A53996C6DCB /* FIRUserMetadata_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 20D8D94C042B585E36891307D12452B3 /* FIRSendVerificationCodeResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 55D4FCD5BAA0A7583F30CF79D5F369A7 /* FIRSendVerificationCodeResponse.m */; }; + 214C0087B11C35AAB34197A6B2A05FD6 /* FBLPromise+Retry.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = EDC8107A0FA008F847D143F5095FCA46 /* FBLPromise+Retry.h */; }; + 217240440770FB45A9B77027674F477B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 218BA22AD876AB6E19146F5A9ABC8F5E /* OIDURLQueryComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = EA086442AADF2F97230F5EE4868D00A3 /* OIDURLQueryComponent.m */; }; + 21C66A6702A435302E9A3BB27D0BCD14 /* FBLPromise+Always.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = CED22AA9ED7E6EE034D56F18A5F55FC0 /* FBLPromise+Always.h */; }; + 21CFB8F992A20FBD84EB32D6966CFB1E /* status.cc in Sources */ = {isa = PBXBuildFile; fileRef = 30CA6D91A8DDF03C7513D55329FD774C /* status.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 221C335FA2AC723CFC2723B66413067B /* FCompoundWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFAA95BB50A7A1D10B42814FAE412EE /* FCompoundWrite.m */; }; + 22ABD8DF323AB3AC8E4D33D1B15052EE /* FIRWithdrawMFARequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F703C962F2095B7778365C9317974D /* FIRWithdrawMFARequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 22BA02A9AF9DDB1A405D82C84953B295 /* OIDResponseTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BB9C5BE4514F02342045406DF9624D8 /* OIDResponseTypes.m */; }; + 23243747D4DADC64049721E4351DEC43 /* es-PE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F854F0655C7BC1A52D8C680D1EDEF4CA /* es-PE.lproj */; }; + 233EBF79D6993F0C86E1B7BBC565F09A /* GTMKeychain_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = E36DB6E3227A68055C28F6B1FC291F50 /* GTMKeychain_iOS.m */; }; + 234AECEEF63D66064976917E97292486 /* FViewProcessorResult.m in Sources */ = {isa = PBXBuildFile; fileRef = C6E90123E0824FF1FE9CD046989FCD25 /* FViewProcessorResult.m */; }; + 237AAD8D6D9697F75230ED02BD359A22 /* GTMReadMonitorInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 576B91C11B11CCAE6FF3C083E2910102 /* GTMReadMonitorInputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 23D1216C52CD698E9A1913D29EAABC66 /* FIROptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A2417F4287F02A9B7CB860818E067D32 /* FIROptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 241723DE0B8689347F719ED670BA6922 /* FIRStorageGetDownloadURLTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5E6C966427FB61A02E3C1DA552D236 /* FIRStorageGetDownloadURLTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 242FDA32EB04264849F3093F8D5FBB54 /* env_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 960C38CE31171CABDBD3DCD719DC79DF /* env_posix.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 2469DC3119A0B851DBE2B70FE1242BBC /* FIRGitHubAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = E224F372FAC278DFD97371C8ADC9E6E8 /* FIRGitHubAuthCredential.m */; }; + 2494C2411E97FD598D49C668DC6B44D9 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A025FC7AA44B6340F0B3D3ECAE5675 /* FIRDependency.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 249E4080458DE5559E6B676D13B1787B /* FChildChangeAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 663809FA696517E7EBFAD50E9D78AD48 /* FChildChangeAccumulator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 24D2FE95FC6B50A5C98D0B8039780BE7 /* FIRCoreDiagnosticsInterop.h in Headers */ = {isa = PBXBuildFile; fileRef = CFAAD0E22DA01E9DCCA50AD43C753D9F /* FIRCoreDiagnosticsInterop.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 24EA386C593881D57578C9EA5233D90E /* pt-PT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 90EF156F21BA67E590DD858B42B6D67E /* pt-PT.lproj */; }; + 2583BF9A374CE74AA576004388BC8A72 /* FChange.m in Sources */ = {isa = PBXBuildFile; fileRef = 15C962C270CF2E0D68ACC36DDF996B77 /* FChange.m */; }; + 258ADA4518173302B8764079C38AED0B /* ic_account_circle3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85CEC317B81F1610CC32F5A36302B5EB /* ic_account_circle3x.png */; }; + 263766BD77E16DF9C72E53C4A4BD1AAD /* FIRMultiFactorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 95D34077E7127C594A944B755B63D902 /* FIRMultiFactorInfo.m */; }; + 266FB1080816C26C4835948DD4C2E547 /* FArraySortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A8163F1A18B941E2293A680A78F8EBC /* FArraySortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 26995FB7C9B15A5B7B916FB103B803C5 /* comparator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0C29E6056C2E52C3272F5DBF03A284B7 /* comparator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 26A998E7E9D58DD710A35F41CE216DB3 /* FUIAccountSettingsOperationForgotPassword.m in Sources */ = {isa = PBXBuildFile; fileRef = 38DFC526013A1EB3ABF8DE3A65E8E47D /* FUIAccountSettingsOperationForgotPassword.m */; }; + 26D55996275D5D789D3F6E7DE7AC9202 /* FUIAccountSettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 46CA62F34B2D8C856819BEB8C5215DA1 /* FUIAccountSettingsViewController.xib */; }; + 26D56FF050B6A9CD6ECF65DBC32A0093 /* FConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F5C88B3CCB1162C269594E5A4400834 /* FConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 271CB6B0B9E91B2F550C0603B5543ADA /* FBLPromise+Any.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C499E907E739C12D9058162F8970BAEF /* FBLPromise+Any.h */; }; + 27431C2385575FFD450126CB6958FBD9 /* GULUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FDFB1572CA5FEEFA8354414A37A218 /* GULUserDefaults.m */; }; + 2744CB0BA0D82371665CFCE6BA1EE3E6 /* FIRAuthWebView.h in Headers */ = {isa = PBXBuildFile; fileRef = 08441C78A0B36E7813F97FB64E0E9B1F /* FIRAuthWebView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 27DAD18D5B0BE098DC0F1B931C045714 /* es-EC.lproj in Resources */ = {isa = PBXBuildFile; fileRef = E9CC25C8A5F883C299D957961F94531D /* es-EC.lproj */; }; + 2808F21DE383D3C9BD0DA03A7B95F6AA /* OIDExternalUserAgentIOSCustomBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = D821A20F4F239BB23077D1E020CD4F02 /* OIDExternalUserAgentIOSCustomBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 288293A8A73A51D6030F539F0DEC0357 /* GTMSessionFetcher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 469ADEDE390A439862C502366722D677 /* GTMSessionFetcher-dummy.m */; }; + 2894DA8F3CFB72FE406F4988B1ABD9E9 /* FTupleBoolBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 8790E43ACFD7A0F4E4F20D3DE7E249B5 /* FTupleBoolBlock.m */; }; + 28A0FAEB4F76BFC6E2B3FF8B9C15F3ED /* FIRStorageMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D664A23B168D6D45A0115AFEAB24697 /* FIRStorageMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 28C913EE8096746CBB939DA315476F10 /* FIRStorageDownloadTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C40D486D4F445531BAB7739A5F3D2AF6 /* FIRStorageDownloadTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 28D20A833E7B75D6CC38C07167549BA3 /* FUIAccountSettingsOperationDeleteAccount.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE79FE50D4F48F8C58CB949DBE4AC0D /* FUIAccountSettingsOperationDeleteAccount.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2907A7E8918BBE6F5A40142AD9D23BAB /* FChildChangeAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = BE6ED932E7AAD7F346281275A45DC1B7 /* FChildChangeAccumulator.m */; }; + 292C7B04F5267FA8DB3DEFEF15478A6C /* FIRActionCodeSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E2B99D595DB983880E6E49B6065571 /* FIRActionCodeSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2949C1B902AB172E5A880292042AC4AF /* options.h in Headers */ = {isa = PBXBuildFile; fileRef = 24C2DE86CB1BC54A75C3E5D22F13585F /* options.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2978FAC39F611ED8607050401A76B277 /* FLeafNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E09E61F0F6E3E1246806D150640883 /* FLeafNode.m */; }; + 29A45C0793FF0DB228A22EFD5ABC91DF /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9B4B8BCB07AC966A24D358AE74A0E6 /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29E94B3A0E4CF892585A606F8064D0C0 /* FEventRaiser.m in Sources */ = {isa = PBXBuildFile; fileRef = 25BCAC05D5A21C8998618E7016194613 /* FEventRaiser.m */; }; + 29EED2DDE45BA8626688A3CDA5ED9D00 /* FIRFinalizeMFAEnrollmentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D613FF318A802CAA63501906CD9204BC /* FIRFinalizeMFAEnrollmentRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29FD58AFCB84370F93925E8DAE5A72B4 /* FEventGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = A3D121E26C7391B5D7DB696193E9698F /* FEventGenerator.m */; }; + 2ACAF4FD734EE4B2A78BEC5DCE57BEB9 /* FIRStorageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 35CAD52DBF73AB5BE8FA7BD10435643E /* FIRStorageUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B268B1D89DDEE445606464B1105E0F3 /* OIDIDToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 57654CEC144ACD0FFCABF85243288B86 /* OIDIDToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2B375405EC4015B14005396C124C4B45 /* GDTCORUploadPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 110B6B1D764C872D7748B1386AF6E5D0 /* GDTCORUploadPackage.m */; }; + 2B4877E9132585C58EB4555226FE3B46 /* FIRAuthExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 30554C35CED21FD072A6C0539122D9CD /* FIRAuthExceptionUtils.m */; }; + 2B535018D357A3B2B56AB7073551F9C4 /* FIRAuthAPNSToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ABB4EE4E5ED740CFBB582C2BB9B50DE /* FIRAuthAPNSToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B83873DFCA886ED30666E5BCBB58AC6 /* FUIGoogleAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 76514376A644F1C0AAD24B289F8F5F35 /* FUIGoogleAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2B9C5DC3D19A8C0C76BA6BE665D9D15C /* GULNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = DB555A10BABB5FF3340F0DA9AA9E7525 /* GULNetwork.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2B9DE014CBDC27683B204852475EB8A6 /* OIDExternalUserAgentIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 332B6F1DCD90DD0A9FABF2C8718B4F0B /* OIDExternalUserAgentIOS.m */; }; + 2C034AC52FF9090141709228E7A67121 /* OIDServiceDiscovery.m in Sources */ = {isa = PBXBuildFile; fileRef = 56BFB5377F78090CCC71859F9C435F83 /* OIDServiceDiscovery.m */; }; + 2C16297567B94FAD20B696F0BA055C42 /* FIRStartMFASignInResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 15CBA6967F032A28843A65A901C56F28 /* FIRStartMFASignInResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C374E3E88095C9C294462506D96C280 /* firebasecore.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = FB9F8446BA7A0A522EE8B2B922D07A7A /* firebasecore.nanopb.c */; }; + 2C3FD200390564CE0BADB770848ED002 /* FTupleSetIdPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 646E13F13038F5392591DBBD166BFDB3 /* FTupleSetIdPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C9085862E0C3305B61C73875F4224A0 /* FIRVerifyAssertionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 38579428D05E6E50944B74FAE19B1BB7 /* FIRVerifyAssertionResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2CE8979B2502607A463ECE1057072C6E /* FIRDatabaseQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = A2A5A1EE7BFC5AF902EB876693194B98 /* FIRDatabaseQuery.m */; }; + 2D48DFD7C608A4732D6AC061FBFDFD28 /* FIRUser.m in Sources */ = {isa = PBXBuildFile; fileRef = AFD9FA2AEB376B05A4B4A9FFA4D1C6A5 /* FIRUser.m */; }; + 2D6BC4E119223FFAAB2C8E4AFC6322D1 /* FPersistenceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DABCC02033CB02917A53BDE950562EF9 /* FPersistenceManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2D8D67C396A0A1A33320AB9924E9DB42 /* OIDError.m in Sources */ = {isa = PBXBuildFile; fileRef = 06E17AEBC3D9DCBAAA1DF718952385F8 /* OIDError.m */; }; + 2DA963F6F10C6432AC2836128677E505 /* FIRRetryHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = D05CA2DAADBBCFD2217247BCBCD077D4 /* FIRRetryHelper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2DC2C023619472E072B8BC7C9D19B14D /* FListenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = B5B759E77F07B7A43FB5DFDE3AEBCD33 /* FListenProvider.m */; }; + 2DEAEDF07164BC2DB28248EDF0971A2A /* block_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = F54FB7D1F60007DA1DA644E4C0BF61F4 /* block_builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2E6B5CAD78D5EAF1C6067E4496107D1A /* FIndexedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 448F29393FE115605D5CA3B7F9E3C564 /* FIndexedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2EDE354B4AD6B2E5DACB4B39363E6DC9 /* FIRAuthUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A0BE22AF48CFFC11F35F50CA46D4256 /* FIRAuthUserDefaults.m */; }; + 2F1A5E7E7CFF3781A8E6FCB4D33DFA90 /* GTMAppAuth-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FDC8EC42195FA6009210D0F20D0C85F /* GTMAppAuth-dummy.m */; }; + 2F6FEC24220A3DF1B9E2C338B230E3CA /* FIRFacebookAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = EC9477E5C763D86BC2707DDA3A103547 /* FIRFacebookAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2F7716A1F8D12F701F0C5BB20D8CC314 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 32EB05EE903C50A94CD83EE48DC0E872 /* FIRLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2F7DE274D6D92482FC6B23802733B4EE /* en-CA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B2C91601666B923A0EC1E3E55055B56F /* en-CA.lproj */; }; + 2F95401E0DA397E88652888DB14DAF59 /* FIRVerifyPasswordRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 509507A836C0211E77888E451937CC3C /* FIRVerifyPasswordRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 30005E7E0F75C7836E14CE4B4E621F89 /* FBLPromise+Retry.h in Headers */ = {isa = PBXBuildFile; fileRef = EDC8107A0FA008F847D143F5095FCA46 /* FBLPromise+Retry.h */; }; + 300DB9EDB10A0681E9D0F77015D7EB8C /* FIRAuthDataResult_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6068E3E88D5B4912A996A1E395BEB211 /* FIRAuthDataResult_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 30517AA89CAE84394D3DB96768672933 /* FIRFinalizeMFAEnrollmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 279B1FA79AC353861C5CF0F52B5147CA /* FIRFinalizeMFAEnrollmentRequest.m */; }; + 3052C53782510E1E0DE4AAA8C5EBE157 /* FWriteTreeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B89883354B04E7224B4BCA94DCD089D /* FWriteTreeRef.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 30834B54C998829A1AC14C31B96F3564 /* es.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C454F063088B3509C6ED0D11F3FF4E73 /* es.lproj */; }; + 30B7536B8896811D74F87E59609BC1DB /* FIRGetProjectConfigResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = F1A95286B9447DB591D70DF43B8B09E6 /* FIRGetProjectConfigResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 30FF3B52E3D4C9C0E207DB078A70666E /* GDTCORUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = F74DEF883FF6125F49131BC4DF11C125 /* GDTCORUploader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 315D40A2C9DACF266A7BA5652244546E /* GDTCCTPrioritizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F2239DC0B4B631FF8BCEFB670B66FD4 /* GDTCCTPrioritizer.m */; }; + 31CC134F37391AE197C14AF757C26CB3 /* FUIAuthSignInButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C363F15AA606162F501DEC2F1C3F71D /* FUIAuthSignInButton.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 31D9DB944C4F02BD02B7CBB5AE188D07 /* FTupleRemovedQueriesEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F642D548971EC7E8066481D6B7AEF05 /* FTupleRemovedQueriesEvents.m */; }; + 321995AB5C5DD22B2DC924BC8F2AF053 /* OIDTokenResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE5385D046245271A0934FA76C066DF /* OIDTokenResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 326F3F512CC15B35883A92F7A4DA86D4 /* FIRGoogleAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = CB2D63A74DA934A6BEF857D02B49169F /* FIRGoogleAuthCredential.m */; }; + 32C15D7F433779E994CB212E90665040 /* GULKeychainStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0353E7DD4FD4E16ACEFB53AC1DDFAC78 /* GULKeychainStorage.m */; }; + 32E4D4F08762CB256AE28F683529F20A /* FIRStorageObservableTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AF2BEA19AA92B905791B5D2A1C4AF7 /* FIRStorageObservableTask.m */; }; + 332623A10AD4F5CD55CA20169E654B23 /* FIRAppAssociationRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = E2E4137B3D3CF49006A9C9F46396C872 /* FIRAppAssociationRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3345F3975DD23AFE1A2F4C96F30AFA13 /* FIRDatabaseQuery_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 085975BA993F8543295A94EECBDD6ECF /* FIRDatabaseQuery_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3347C5B0CC6F9D2F6F791ED570E53525 /* FIRDatabaseQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = DBE2AF1FF99BA0861976B62FD7FD819E /* FIRDatabaseQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 33A030CB4B6202E221D82324542DAA62 /* FBLPromise+Delay.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CAEE40E2A06A4534FC90D028269EEAE /* FBLPromise+Delay.h */; }; + 33A4845D23193343A2636B220E0D98C8 /* FIRStorageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = C9833FD8B66A1AA07AFF0687BAA33286 /* FIRStorageTask.m */; }; + 33E51598939F4C04843B589E45A77A94 /* FUIAuthStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = FF280DA876648901D57970E5E26947C0 /* FUIAuthStrings.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3401AFF2A97BCEEF3FE0B3D9DFB23C7E /* FIRInstallationsHTTPError.m in Sources */ = {isa = PBXBuildFile; fileRef = EB41C29425BE808F8982F4294DDD5D1E /* FIRInstallationsHTTPError.m */; }; + 348E1522ABB9E9CB80C3FC0F02EDAED0 /* FBLPromise+Validate.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9EA4E84EC07EDEE7CEB2CF5CB07768D0 /* FBLPromise+Validate.h */; }; + 34C640803490355CD526FBA17DE1BC60 /* FUIStaticContentTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3B3028D10F8D06C2A88AF313F76CDC /* FUIStaticContentTableViewController.m */; }; + 34E1C2E17BA70DBF58D92755072E5116 /* zh-Hant.lproj in Resources */ = {isa = PBXBuildFile; fileRef = DEBE75C4F3E332C7AB0A3A2FDAADE873 /* zh-Hant.lproj */; }; + 34E362FA2EBC79F053D69ED32EF50B2C /* FIRPhoneAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = E0EA93F03F796711CD33A8D1A75BE58E /* FIRPhoneAuthCredential.m */; }; + 35018015F6FFE61A4F46B65E2845FD50 /* FirebaseInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = FD4A9A5E7A8A9588DF99DB175B94644E /* FirebaseInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 350DC6598D772740CB7F40C7638023B5 /* FIRVerifyClientResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E6CE7028A24474F1C666BEEC7568971 /* FIRVerifyClientResponse.m */; }; + 351C3BD4DEB2E7F2EFAB7D826D7EE53E /* FIRAuthAppCredentialManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDCB2F5383C1A7C7A91F0F135CAC071 /* FIRAuthAppCredentialManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 351FB1285EC73346A4BA5135B8E521B9 /* hu.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A1045ABFBD7DF90A5E84372D88E5C833 /* hu.lproj */; }; + 35242D43A8DB0D76B1ACBA58DA65F7DB /* FAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD2BED9DB9379A85F50B0F047351FC /* FAuthTokenProvider.m */; }; + 3534B7679EAF6E73DD83126C1EF852DC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 355CF2719234ADB11A1993E2120CC373 /* OIDTokenRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DF71716C207DAB7D4A96B5EC78F76FE /* OIDTokenRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 359FBAD9D5DA5BECE0F296EFA2E8E765 /* FIRGetAccountInfoResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = E127A35AD926485DF36164AB3C03700D /* FIRGetAccountInfoResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 369AD08B841718216F3CD510659C0459 /* FClock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E73E913D6BE2187678163C216DF1BB5 /* FClock.m */; }; + 36D9504FDB889AE9A1B4AB4FD576607D /* GTMAppAuthFetcherAuthorization.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FAB6110EBCEF5EFD9AAF97FB1E323CD /* GTMAppAuthFetcherAuthorization.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3702D305A0003D5087C0F175605EEEB1 /* FIRComponentContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A64636DD51D9160A5B0AA9214A30129 /* FIRComponentContainer.m */; }; + 37057AA414B5BE96F00FB5CC635D1356 /* FIRCoreDiagnosticsConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = DC32670B925412C8F39FD6CAB0A08327 /* FIRCoreDiagnosticsConnector.m */; }; + 37465688E43C89C656D5CACBC39A2E90 /* FIRStorageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = CBA6A06C975D6C6C939DB4CB58EF49F8 /* FIRStorageDownloadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3746A7ECB545CF4FC344F47B4BEFA1F0 /* FIRStorageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B02D893464CD1AA4EC9495A6C0FBAB6 /* FIRStorageTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 37DDC4C15E27EB7E2E2A0E852F5429D2 /* FIRDatabase_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = A2A714EBE8E059F6E1C1162A7AD08015 /* FIRDatabase_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 37E7849CC2713E6140E4FAF8421B842D /* FIRCoreDiagnosticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = A97A1D0B0968B8B21FB213A4A8E8AD35 /* FIRCoreDiagnosticsData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 38367D3DC04822D1C105141FA957CBB9 /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 73DDA3AD22CD6A161783A626C136DA24 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 384EC29BF90AF67506B23E48F2F23B9F /* FUIAuthTableHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 51B79EA8514AB2DE5FB6E83BADD37011 /* FUIAuthTableHeaderView.m */; }; + 3858E1DA25778132A8EF8E7F1C27F8B9 /* FIRInstallationsStoredAuthToken.m in Sources */ = {isa = PBXBuildFile; fileRef = AE454B37B7F5959A0D2816E4BAB48C6C /* FIRInstallationsStoredAuthToken.m */; }; + 387BCCCC3FDB1BCECC6B8C541B95B0CB /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C824D703137DD9400773104180604FD7 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3887AFED9A7EECCDD1BF72AD99D26EB5 /* GULNetworkLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 55ED76CB4443F7E041AB9AC6FA9AAB50 /* GULNetworkLoggerProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 389A5B099EF8432E317DE7FF3C0DAC13 /* FBLPromise+Testing.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 818E56D83F281D68C11461EBA7312C1E /* FBLPromise+Testing.h */; }; + 3966411927DD463FB7CEA504A9188D8E /* FIRSignInWithGameCenterResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 8075BDC5128A59A8A356556917442DC7 /* FIRSignInWithGameCenterResponse.m */; }; + 397978A03CC7F1E8F1F0109235EED82C /* hi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 78A548A17202BBEBCAD3914415FA6185 /* hi.lproj */; }; + 3989F5BDEC4A21202F727FB35ECB9E4D /* OIDTokenResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 68C12C2F05F8845F2117F2E65E74EFDF /* OIDTokenResponse.m */; }; + 39D4516A2DB8E91D2A1C0CDB79BDCBCE /* OIDURLQueryComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 42488D1FE841F575C61D519426D4364C /* OIDURLQueryComponent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 39DE7A791BCDC4D4801C252870521687 /* zh-Hant-TW.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 868E02358BA6AC33B570F4302DD9FE18 /* zh-Hant-TW.lproj */; }; + 3AFBEFD6D27A5D2FC0D30799DDE964F8 /* GDTCORConsoleLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B2F71602C9A737FACA970FCE8F7BD7 /* GDTCORConsoleLogger.m */; }; + 3B049D61D103398556EBDF0F4D703FAE /* FBLPromise+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FF2415F7CE0F63E2A28F7B9E7F203F /* FBLPromise+Testing.m */; }; + 3B0E9B0B629DF07E6A8AFA719F59A567 /* FUIAuthErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AC5C1368897ED0DB6D31746B4B0ACC8 /* FUIAuthErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3B5E0A803F680A69149CA6CC2291C34D /* FBLPromise+All.m in Sources */ = {isa = PBXBuildFile; fileRef = 69279375BEBF6427D31ED9DC4A523D78 /* FBLPromise+All.m */; }; + 3B9227E12D80A9D65A23A7B7EF3569A4 /* memtable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C8CF2EC8254BD9488FC31DE753FDE52 /* memtable.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3BC1F2F0CA2F65570B44D5D06B59FCEF /* lv.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 187318BA2B8C87BF94F4551700E3363D /* lv.lproj */; }; + 3BFE8CD59118C4908BDCF67DA762C118 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = F31F9DA1BF7C971697A98B2825B32A75 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3C2146EE415B38ADD4EF547E5855A2DF /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = EB2E4DBCB2D2FCA11BE0532ED759FF12 /* FIRErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C4B9FC273F97FDB310FC2073B0ACC0A /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = D94FE53E1C3A87669A08349FFCB1A1F9 /* snapshot.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C682F1D7F9A25A96B74D376E64FEB6A /* FArraySortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = C391CAD9145F4C9DB23A38E59BB34A20 /* FArraySortedDictionary.m */; }; + 3C719CF3EF732FB873BF085084EE0940 /* write_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3EEAF9534B473AD61A7AB54C40B9FEF1 /* write_batch.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 3C8CC8F8E043DA9D5BDA8C1F40309100 /* FTupleSetIdPath.m in Sources */ = {isa = PBXBuildFile; fileRef = EC9F5D9D34F3AFD51FE48B10DCDAE1FD /* FTupleSetIdPath.m */; }; + 3C9648C34F26FBD8B635A0D3A185F779 /* FirebaseAuthVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 31403F1670FC70281DB296638EBBA5C0 /* FirebaseAuthVersion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3D0E9CEC2B277749E2CF4CF24289DB8E /* FIRAuthRequestConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 331717291051CAD5BB3353BB8C494A50 /* FIRAuthRequestConfiguration.m */; }; + 3D5DA7C62B87D9300E6FE1C017D5D018 /* FUIAccountSettingsOperationUpdatePassword.m in Sources */ = {isa = PBXBuildFile; fileRef = 428A36C062A2962BC3100F2C0FC17BB3 /* FUIAccountSettingsOperationUpdatePassword.m */; }; + 3DA80B564E29D5DB2CEF425EB334E919 /* es-PY.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 778802077ADDAF4B7A52B59847FE54DB /* es-PY.lproj */; }; + 3DAF0DCDD6C3F9795DFACBBF4F6CC6AE /* version_set.h in Headers */ = {isa = PBXBuildFile; fileRef = B70A99DE047CDFD48AEAF4818A9AA25B /* version_set.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3DEC7494C09A62FE6B75E0B4AD0AA5F8 /* ms.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3F1B7DBC84792CBABEBA9ECF5DBBB256 /* ms.lproj */; }; + 3E012F2BD62CA7B586A77595AE407C2B /* FBLPromise+All.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 2D2DDAE0A59EACE0F9CF5B3655B713FB /* FBLPromise+All.h */; }; + 3E0721C5FA7BB41B555DEFF6B63C784F /* FIRFinalizeMFASignInRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F6CB189D81B7A5D42DB2B7674676C63 /* FIRFinalizeMFASignInRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3E2B62DD286BFD7ED1A58BA440849967 /* FIRVerifyAssertionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = DDFD93E377D4D37AD058840107B807F3 /* FIRVerifyAssertionRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3E300FD7FB5B126C68BB81C83C32F848 /* GULNetworkURLSession.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE9C52C8EB244E7F293F1632DCEC5EF /* GULNetworkURLSession.m */; }; + 3E52BA6652B376B3185D2020446B6DD6 /* FUIAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6DF75AC07EAEEFBBE8B2D16DA1929E /* FUIAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3F1F361AAA196EC3433653171B98900A /* FIRStartMFAEnrollmentResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 20BC6706A3B2DCD001B2917F79F8F31F /* FIRStartMFAEnrollmentResponse.m */; }; + 3F59B34B610EAA5F1DCC24E8825BA167 /* FIRGetProjectConfigRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 74FF9CA663893AB6239A094AAAAEA2C8 /* FIRGetProjectConfigRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3F609DF53628B2F834F882C40F39C99C /* OIDTokenRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E3A8051121F638EC5568C79DAC199BA5 /* OIDTokenRequest.m */; }; + 3F87E8F7B86DB236E23F6C3A00501A0A /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E5F5A39D1BA88D7C06015AD44FDE98F /* hash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3F8EA09FE4E8A77F350D2975EA85234C /* FIRAuthNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE4774B8121D656C797F2900CD8BDBE /* FIRAuthNotificationManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3FA835A1652626C3FB69DFD515DF1A67 /* FIRStartMFASignInRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 97B15D8306560971C11A226391C02BBD /* FIRStartMFASignInRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 405232561081E4DA0F2FF77DC0EFB0D7 /* FBLPromise+Delay.m in Sources */ = {isa = PBXBuildFile; fileRef = 573C2D9A17826A7450441A7FBCCD3014 /* FBLPromise+Delay.m */; }; + 4058ABDF86E73027AD91B36D1E0F4326 /* FView.h in Headers */ = {isa = PBXBuildFile; fileRef = 907BBDD52C7ED77CC879E7EA2FF71132 /* FView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 408352680097A53851035145970371B1 /* OIDAuthorizationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = E61FAA8E21834BFFB167837F4917911E /* OIDAuthorizationRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4092A1D75E185C4A5AFA4BB2CD98058A /* FUIAuthBaseViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 234F4C1B718C50970467A34598D11AEF /* FUIAuthBaseViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 40BC0E0EF1FE17A85517CA882F24ADB2 /* FBLPromise+Do.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E5F43CF7B994C577E41DD7E44C33231 /* FBLPromise+Do.h */; }; + 40FC84D2AFB6832635DD9A929E516BAE /* OIDGrantTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 261D24E6A7E8FE448A9D6BBDBEAE06D4 /* OIDGrantTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 413F760343B563758599EFD78245EFD7 /* GDTCORClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AD16C64DC57BE00921DFB26B3E88660 /* GDTCORClock.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 41566374E119EC4270C38711624E1D01 /* FIRAnalyticsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 96F59E405A529746B24F54B8A9CA58FA /* FIRAnalyticsConfiguration.m */; }; + 4185C11FFE1B63D2FF34FB7B53674C84 /* FIROAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 9374F6D4F9703C1046AF6A58B1D1F189 /* FIROAuthCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 41CE7886546CDEE018D896EC2B8120BF /* el.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 79A12CF03274F6EAB14327C8ADDDC0DA /* el.lproj */; }; + 422A451F139979443688BD7BE6511256 /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C95D1C7C8FCD7CAF183BC0E158F01C7 /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 422F4D572554D7A70D0A7BAABE0F99EB /* FPath.m in Sources */ = {isa = PBXBuildFile; fileRef = FC7E3FA7EA5372B5C2C86F26E4BE5033 /* FPath.m */; }; + 423B4495E135FE5C0ED0B4071E8BE0B5 /* FIRAuthAPNSTokenType.h in Headers */ = {isa = PBXBuildFile; fileRef = 64548224BB9A1948AEC7FB891E88BB5D /* FIRAuthAPNSTokenType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 426BC23107C5F23894ECBE1D47329FC0 /* FIRPhoneMultiFactorInfo+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = FC0FDCC1AA88D683B0D4E35474D6DE84 /* FIRPhoneMultiFactorInfo+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 42902A1836055088CB9CE3031ABAB20D /* GTMSessionFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = F816F516E077044050B35F73606B9143 /* GTMSessionFetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 436A7138CFF866F2575CBE9FF6E4EC23 /* db_iter.h in Headers */ = {isa = PBXBuildFile; fileRef = BF8A0755D032262E220C5286C9CCF2CF /* db_iter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 43A17DD94A43D97AB409CED1E7BA186C /* es-UY.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BBE953CA3053CC11FBB998F65D10C853 /* es-UY.lproj */; }; + 43A408791A67AA75FBCBE6587CC3DEA9 /* FIRInstallationsAuthTokenResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ACC5CF4825F2AD7C86F0B0739E82CC7 /* FIRInstallationsAuthTokenResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 43CD721013246C189057E90A15D23676 /* FPersistentConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3321CB5DB4DF1C493E717FC8351C71A4 /* FPersistentConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 43EF2CA6A6E51F8A6C883103DD9612BF /* fi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 60470DBAAA6781680A41419A079C8788 /* fi.lproj */; }; + 441867214FE4F98B0C9F20E21208F7FC /* GDTCOREventDataObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C7618A96808C4D7CEB9824787ABB4DD4 /* GDTCOREventDataObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 442D681AB88C1CEFD0857BD3B4BE323B /* GULSecureCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 0889F6ED1E26D93D3A5813350CCC106E /* GULSecureCoding.m */; }; + 447B106C81021B25A65FEB3686397CE9 /* FIRStorageDeleteTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F77B33F5B4224F35E3F624BE59553B38 /* FIRStorageDeleteTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4480D20BAE2A84682B5DE51F51A5DD4D /* OIDDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 48FF0BF87B15F6A87546A37B2BE1679A /* OIDDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 453AE47A48F9C3F188D8209C0B0A6772 /* FIRStartMFAEnrollmentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED5B5B260DA1124ED4F9279DD4FCC12 /* FIRStartMFAEnrollmentRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 45514530A4C6DF33B53542A269A20CCA /* GDTCCTUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F423EDD6CE2FAB275E51626151E9B5B /* GDTCCTUploader.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 45A8AAAB778CA6885AD806CBB0B5929F /* FIRPhoneMultiFactorInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = D8115227BAC33FB3D00E2975EE0BD24C /* FIRPhoneMultiFactorInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 45E5ACFE303C1B6358F8C7E9511A6386 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E942549C86F57C477E3AC759C80C513 /* Security.framework */; }; + 4615E2A1CBD25268150CDAF59E2BD92E /* FIRStorageErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A44B8B2E53063933C325653CE73494F /* FIRStorageErrors.m */; }; + 464EC1E08DCD9058DE9AAB2873F05385 /* FRepo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 294612EF265084E263D9B8EF81CEF4FC /* FRepo_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46B91B7AAA7B562A8D6F9333B8BB3252 /* FTreeSortedDictionaryEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE8D1F47D22F1D6FAA6945CA508BFB12 /* FTreeSortedDictionaryEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46DE09E96BF90F4A6F8A2B139DB6AE10 /* FIRServerValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 912B58F48447E074A2D77B3BDB573ABE /* FIRServerValue.m */; }; + 46FB6ECDDDE2D572789A81EA97B1DD42 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = B8FC9290AD16001E5097C8CDEDCEB32E /* FIRLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 470345F04DB08B636AACE884401CC35F /* FIRPhoneAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 979EE14740E14EBC7F7EC39F2D7B7574 /* FIRPhoneAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 47848239DE7CE0B630760AF64F106DFA /* GDTCOREvent.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FD5A9390F75691B9442F5ADA1BA075 /* GDTCOREvent.m */; }; + 47EA5899C0B22CC37171E11A9062D368 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 78E128753A283DBACD262E6F97C1D738 /* it.lproj */; }; + 4845DCF4EE3FF7CB6159399E626B7500 /* FIREmailLinkSignInRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 843D31A14C08E44DE861EC9068CF935A /* FIREmailLinkSignInRequest.m */; }; + 4870D0FB963B09D3D9FAA4E3DC9263FB /* OIDClientMetadataParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = B89C71BCD83F5C915E0B7B88E0783F5A /* OIDClientMetadataParameters.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 487B398FF6DE0468B5E8E4FEBB432327 /* OIDExternalUserAgentCatalyst.h in Headers */ = {isa = PBXBuildFile; fileRef = B780FFAC1852977D9C50DEB819B56185 /* OIDExternalUserAgentCatalyst.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 488F8D1191176DE786AED6FC1824241E /* GTMSessionUploadFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CA67D99FD590B97C671527224321D3 /* GTMSessionUploadFetcher.m */; }; + 48F68DF275ECD44FC2CDD440C6A978FA /* FNextPushId.m in Sources */ = {isa = PBXBuildFile; fileRef = F23F6A10C23DA53CA0245A145EF508AD /* FNextPushId.m */; }; + 498E5187AB1A0FC9D170F9E0E8A06989 /* FParsedUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 26A701B9267F7E760B27DF5EFD4E534A /* FParsedUrl.m */; }; + 49EABDC78CCC02ADA8BC3C106C02AFD7 /* sv.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4BD64D667BE6E644D010A4C6AB245206 /* sv.lproj */; }; + 49F8C0EF3592024C925614A281987956 /* FIRApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ED22E829FF20FF3C96668710289B582 /* FIRApp.m */; }; + 4A2E5A6D3A0427667DCC4F9965365315 /* FCancelEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D8CC6D3E8DCFA0BC10D29F0D214F685 /* FCancelEvent.m */; }; + 4A619B3454E7EF3C9E3712D438196E85 /* bn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BDF69634B5F3A7C722770C9FA296E0B7 /* bn.lproj */; }; + 4A78E6B8EBB9E5AB9FA957E4F8A8D0D8 /* FIRStorageGetMetadataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 370DC54124A24E6D2D89067F66C8807D /* FIRStorageGetMetadataTask.m */; }; + 4AADD8428B871D93442D79F99770CC48 /* FIRHeartbeatInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 09D08393443CCDD8CF77D6023BAAC3A4 /* FIRHeartbeatInfo.m */; }; + 4AB046B92EB84D420565F315B38AE0E1 /* FBLPromise+Recover.h in Headers */ = {isa = PBXBuildFile; fileRef = 169EC26D74379B8E784D2BAD7F05FBAA /* FBLPromise+Recover.h */; }; + 4AB5AC141FC39871632CA5470D4513B7 /* FIRStorageGetDownloadURLTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3B1BAC7E72143AD4BA76261839C839 /* FIRStorageGetDownloadURLTask.m */; }; + 4AB84171CC0E53C6D2BF6B264EEAE02E /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B646542193B39A1752CBECC2CFB5F39 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4B0C4ED4D4B05D0C5EAEA9637B4190A8 /* FMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = D20FAB51BF2E33A9F29B6692D52010B4 /* FMerge.m */; }; + 4B22653EBA41D18BE1096ED6473BCE0E /* FOperationSource.h in Headers */ = {isa = PBXBuildFile; fileRef = EAAE124D4FDC12A2A98D95D218A42E38 /* FOperationSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4B2EDDE16EC22B41C5B7E73CBCDC80C5 /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 5007EEBF4BE55DB72D5EE4CAA00E4C5C /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4CE71BDDC889ED63366C102275C1DFA7 /* GDTCORLifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 02B3AF231CF542962F689F76E52481E7 /* GDTCORLifecycle.m */; }; + 4D2C23B725FFED954CDE8F4DE5DB7155 /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F37DC0D68E2ACE25E446599F0A6124 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4D50D00D2C5E7B21A251891CF7AF88FE /* FIRFinalizeMFAEnrollmentResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 77AC5C0D1A2EAB140E1050E088AAC8AA /* FIRFinalizeMFAEnrollmentResponse.m */; }; + 4D603A0713102211BB0DACD4C78A1AA1 /* fr-CH.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0F53635464E43DABB555A566F5EE35DB /* fr-CH.lproj */; }; + 4DFB2DC386C65A06CBE4D5D900B87C38 /* pb_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D00A435DFB725951078FD373898E52A /* pb_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4E74CFEC8D60E119422E2D8F20389F26 /* FirebaseCore-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E0A693BC5175C7A316BEAA2AB79D1605 /* FirebaseCore-dummy.m */; }; + 4E9FD6CD2C6379A3F8365E46CE7AECCF /* FIRInstallationsStoredAuthToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 76C1B4F4BBB24C931633B0FBBA0B87F5 /* FIRInstallationsStoredAuthToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4EE48AB3A8196BBBC226D648564B6D07 /* arena.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7D1C0142C1B858F367068429A25E9A45 /* arena.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4EF38065E0F4C054D7D005F503EFB2A7 /* he.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F571E596E02E04A50AD81E7326931D0C /* he.lproj */; }; + 4F0D14FBA4491E440C863A9489D0D7A1 /* FIRComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 953C2D3F948748A2BD8EA7A019A49819 /* FIRComponent.m */; }; + 4F2180FBFFD05BE4EBC767685881881B /* FBLPromise+Wrap.h in Headers */ = {isa = PBXBuildFile; fileRef = F8B0B924EF0FBA3293977F67BC3ADB6A /* FBLPromise+Wrap.h */; }; + 4F2AE2ACC6468002D20E6F9FF150235A /* FBLPromise+Timeout.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 50BD34FADDD845EBC8222D9EB3995F05 /* FBLPromise+Timeout.h */; }; + 4F949070B5291E48CF5EE510B4C4956E /* GTMKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 810D84765A63AC3EFC5E3C943E7597E3 /* GTMKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 504B56632F2230AD3EF1B88DAA787A96 /* GDTCORTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C927FF92EAEBC5B576C5C5ACD1BFA00 /* GDTCORTransformer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 507D282C5F13D1AE71CD2F3725C38EEB /* FBLPromise+Reduce.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FA2962149836A8999CDF110AAD149CC /* FBLPromise+Reduce.m */; }; + 508ADD9B844C25C9DA688D46A8D6984A /* FirebaseStorage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 39720C2178180584478CFED5FB451DA5 /* FirebaseStorage-dummy.m */; }; + 50A22F3F84F6220DB2664EDBDF67AF3F /* en-GB.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 76C514358FDBBCF9A559BE493725B973 /* en-GB.lproj */; }; + 50CF6B7980DA6B852D3F3F25E2B38767 /* FUIAccountSettingsOperationUpdateEmail.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F76DC8A393D84B5EC545F11C33B1C04 /* FUIAccountSettingsOperationUpdateEmail.m */; }; + 50F995B1B2C6D541C2A727889F65178B /* FBLPromise+Async.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C4A53C14BCDA2F6609BF3286C408518F /* FBLPromise+Async.h */; }; + 5104242D4E06A17005611E178D6A603F /* FIRAuthGlobalWorkQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D2A0CFFCC140A4E6C194F8D0FC5D628 /* FIRAuthGlobalWorkQueue.m */; }; + 5114E10BC50187991D597C59683980E9 /* FUIAccountSettingsOperationDeleteAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = A536C5536C394A6E8669C73E0EB32186 /* FUIAccountSettingsOperationDeleteAccount.m */; }; + 511E46864C6515E5D54655E4329570A8 /* FIRAuthTokenResult.m in Sources */ = {isa = PBXBuildFile; fileRef = D2A7778C875EA74A7A8967EDFCD4A25B /* FIRAuthTokenResult.m */; }; + 51D3265F64214D5D68BC9B514690EA07 /* FBLPromise+Catch.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E687CA6920D53CFA44E0E9B9ED3E2A /* FBLPromise+Catch.m */; }; + 521833776E43C7D9F02117060F8A53DC /* FBLPromise+Await.m in Sources */ = {isa = PBXBuildFile; fileRef = F451879A1A9A3D5704CEC1CA6EF6F24B /* FBLPromise+Await.m */; }; + 5248ACF7F7182E21D852B2730B3ED205 /* es-CR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 42914413BA6F0875F89E6B59303ACC41 /* es-CR.lproj */; }; + 52B867046F638CE4D25775B97F87FA75 /* FLeafNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ADF4BE0B984457784EB53A44B4AE301 /* FLeafNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 530111D3B0DB8821E9CD13B69D54E8C4 /* FPathIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F122A33B14CBFBDCBB14223CE8EDD41 /* FPathIndex.m */; }; + 530C06EBE16B197E16F0E8DDDFDA3CF2 /* FIRAuthBackend.m in Sources */ = {isa = PBXBuildFile; fileRef = 473112A3CDA01CDBEC8924CAD7682B96 /* FIRAuthBackend.m */; }; + 53775BAE742788CDA4B9961F552B5F90 /* FValueIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9627E22602C602EF52BFF49FE56D98 /* FValueIndex.m */; }; + 537EEE67A109664A97D0D2D59838A10C /* GULAppDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EEA4E41181C12F276CA21332BF193E0 /* GULAppDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 53D54F6DFDACF1214F2B604B28CCDE06 /* FIRGameCenterAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C9DAD4624BF9ACE5C50723DE347FA8F /* FIRGameCenterAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 53D9A922A43771043C21040DDA0F0DAC /* format.h in Headers */ = {isa = PBXBuildFile; fileRef = 82048231EF2E3884801064A817757265 /* format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 545485FF7CEA9AF03EA8900B7C955389 /* GTMSessionFetcherLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 413021A56F2BD5431D883E691672D672 /* GTMSessionFetcherLogging.m */; }; + 54A443E1D801F03B18C7EACD11EED750 /* FImmutableSortedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = AFCF7CBD5A6947B40B936E1629C4CD6B /* FImmutableSortedSet.m */; }; + 556349A2E90B66ABA58FF61671CA7ED5 /* es-AR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = CEBEF2F06D0AD7AA80B541C2D95934CE /* es-AR.lproj */; }; + 55683A039086EF179B1B058EC5BDA235 /* FIRLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E003F27645520032E3624A30B1B9E93 /* FIRLogger.m */; }; + 5588AB3DE0541FF7D1BD89B8DAE0419C /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C74BB36833DAE2734F5679B8EE2E04FD /* SafariServices.framework */; }; + 55CE468A3EF488AF96C380654BEC4B74 /* FIRStorage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = F04402C3845EFFC388DEC264ED5CA75D /* FIRStorage_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 55F2731B30483A892593B5CE9A6E133E /* FIRAuthInternalErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = C6959E1A1109365FD844CBC9D553F283 /* FIRAuthInternalErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 560CB000DD26855FA975032136CB0006 /* GULMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = D983B95F647C6BB9155FCAEA8E9C39AF /* GULMutableDictionary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 56308A63BDFDBE75095A40BA349AF437 /* FIRCreateAuthURIRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = F98BAF8C84B54154210F7ACBE4D637A0 /* FIRCreateAuthURIRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 568235CAF30B5BBFDF4E7A6D18C70517 /* FIRUserMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = C25D07BAAE13143BC5F5C71355C0D5B6 /* FIRUserMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 568276FDBFC7923067446270D62B39CB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEC5BAE613C9C504615D4DFD6BA5F32E /* SystemConfiguration.framework */; }; + 57178F706DA28A0DC053EA56DB9DBD7D /* db_iter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 34B5C51512525AB5568CAA468C878994 /* db_iter.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 571E78F80A43E8011456893D29F36D15 /* es-HN.lproj in Resources */ = {isa = PBXBuildFile; fileRef = CB8FE127E94323EA8191DC5075AED4FE /* es-HN.lproj */; }; + 5722E3D3D0D0F9BCE8C1E6A2822A9DC9 /* FValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CC0A3191504AAE5AC701D8DDF35DB9A /* FValidation.m */; }; + 572AFA503D9E766A04337DE770226322 /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F36BCB3D0BD01DDB626C5FE3F73DFBE /* NSData+SRB64Additions.m */; }; + 5757C63ACB8CAE9CF3A315D64F51299F /* th.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 6ADA72465BC54012D2E01EF0E369AD84 /* th.lproj */; }; + 5795021557FD78AA2F276AB2493C0A61 /* FIRInstallationsLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4803EBD15BE98DB688A0189ECD4ED8 /* FIRInstallationsLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 57A5799EE36CD3738E4AABC8602C7EFE /* FIRInstallations.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C9F8DDC9502A6EE00DABC661FA82ABA /* FIRInstallations.m */; }; + 57D8CE3355759AE954FCF0C0F918E3C4 /* comparator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EB6C4F707D6AE247061BDE99F5582DF /* comparator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5829B9395462EC3F409DC8AEF8F106A4 /* FIRResetPasswordResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E3B94329AF814460FDA387EC4AF66927 /* FIRResetPasswordResponse.m */; }; + 58388FB6F90F3E8F46C1B59E8CD02A7B /* FUIAccountSettingsOperation_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C74A51246137BE63D7AD4A74D0FD7D9 /* FUIAccountSettingsOperation_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5852D1793638B975393CF5B6D6C21B52 /* FIRVerifyPasswordResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 64EC6A649794171EB333535CC75C27F5 /* FIRVerifyPasswordResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5904666A636D27B7AFC0BD1B17300206 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFA7D192C54AC5633BAC1203D5FB145 /* FIRComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 595648786E3F08A8DE701E00B1A50E4D /* FIRAuthSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A5EFA30C44EF4FB68F3C3D45A179EC3 /* FIRAuthSettings.m */; }; + 59731CB6F46FF7F63F6A400542C8FCB1 /* es-CL.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 23C82953FC80B9C61F784D4B27E54E19 /* es-CL.lproj */; }; + 59902A903D69F70D9B5D1A04374AC404 /* FChildrenNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E1FAFA86993C6014868FA31E61087E0 /* FChildrenNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 59F5C0E82357C75D1917ADE67FE8F648 /* FListenComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = 719D94D75C5E235B7C3E2F38110E1402 /* FListenComplete.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 59FEE0211B52A4CCFE5DB2179A01FF9B /* GDTCORReachability_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 44D9AD5C042BBE2D118A698A9E5E76EF /* GDTCORReachability_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5A2092F7D72C888A4C9BE7400E7C18B0 /* FIRInstallationsAPIService.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B327A0258B05487FBCADDDB623B798 /* FIRInstallationsAPIService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5A39B9D6AA724294CCB0066871D35639 /* two_level_iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6CD6E75538335D0C15F77F90238740C8 /* two_level_iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 5A49BE780BED21747E5BCB544F217DE7 /* FIRTransactionResult.h in Headers */ = {isa = PBXBuildFile; fileRef = AAD4D44993BA05A2CEEDCFB4AEF3E45F /* FIRTransactionResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5A592B3EC4BC8877387D08796C9A55F7 /* FirebaseGoogleAuthUI.h in Headers */ = {isa = PBXBuildFile; fileRef = C612507BFEF47D61B5266674121F2A68 /* FirebaseGoogleAuthUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5AA89ABC4B1EBCA16BF7BFBEE96DDE5C /* FUIAuthUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C3645F8ACEB96B24FFEE072C49B858A /* FUIAuthUtils.m */; }; + 5AC2CDD3C635A465DDA6FD5E9F38BD47 /* FUIAccountSettingsOperationUnlinkAccount.h in Headers */ = {isa = PBXBuildFile; fileRef = 87174475F1969D1150949EC200E43A9E /* FUIAccountSettingsOperationUnlinkAccount.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5ADED25080F594D8FD890C75F682AEF1 /* FIRDataSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 079E3CAFC7164BEDEA7B74133125300C /* FIRDataSnapshot.m */; }; + 5BC15725B1ABE70CB2B617F6871F14D6 /* FBLPromise+Async.h in Headers */ = {isa = PBXBuildFile; fileRef = C4A53C14BCDA2F6609BF3286C408518F /* FBLPromise+Async.h */; }; + 5BCEEF371F011913FB019D3085CDC9BD /* FIRUserInfoImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = C8DFE6DAEF4281B9CBB00EC08215796B /* FIRUserInfoImpl.m */; }; + 5BE34532594B80EFE8E63750EE123CCF /* FIRStorageConstants_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B0AD5E6656068EFD990FF19F45F0202 /* FIRStorageConstants_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5C20C1714B7AEE5D603261CBADAC7DA8 /* FIRInstallationsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 544356950C800EB743CC174C9ABFCCE8 /* FIRInstallationsStore.m */; }; + 5C38D5226A33ABAD5FCB1A600AE8C130 /* FEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = E5D4C62D339CFF2B64B65C4480F11094 /* FEventEmitter.m */; }; + 5C43E64B8DFCE99DD92F62D538C0DFF0 /* OIDFieldMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 585ED8010AE1A4B72569E70262072162 /* OIDFieldMapping.m */; }; + 5C58345D7984850A8580C632746ACD99 /* FIRPhoneMultiFactorAssertion+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 494F76FE5143C8D636FE5CAB2CA7372A /* FIRPhoneMultiFactorAssertion+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5C951A44B81A828A3485F607D8A7C113 /* FirebaseCoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 984741AB13FDFAE0FBB3AEADA04EDBBE /* FirebaseCoreInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5D018C896E2B857D71EA72830177FFDC /* GULLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 33E64FB96AE1E5878000B5A0DF0ED00C /* GULLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D1F6D179D2E6DDBCF8CA745F167FAA6 /* FStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C76C26999C5EBBF7EA157465C0939D5 /* FStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5D34DA34E00D1CE5B2BC83FE04DB0037 /* FIRUser_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A38DCEB8119B8F88A776D0122E0642 /* FIRUser_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5DA0CC1B1C6EDAE286F217F846C528C7 /* ms.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C3671B246F2292948552AA5DC9D688A0 /* ms.lproj */; }; + 5DAEC63FC80477A0171EA77AEAD16BDA /* status.h in Headers */ = {isa = PBXBuildFile; fileRef = 614FD0C542050D26FA76C49E96603020 /* status.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5DB69E5C7D55E41ECD5D6F0D8F0A29CC /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 61FECAF9DDCFEB0AAC6EB34E1F4E9795 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5DE5ACB9424B4D9130BDC8FE8BD41307 /* GULSceneDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 68C28E759956387D8E25CBB6785BC93F /* GULSceneDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5E35721415C0903BE370D06334C27713 /* GULApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 78DB579CADEFEB232525FF20715796F3 /* GULApplication.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5E4F12FEAFBCF393F56C65655787D7D0 /* FIRAuthUIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BF1EF2B382CEE39048BFA8A04FA59482 /* FIRAuthUIDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5E6454BE594C67BDB528E18B85C62801 /* de-CH.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1EF65A483BB4A3FD7205F21724439323 /* de-CH.lproj */; }; + 5E737B44E6DA0B67D19959B426B12F2D /* FirebaseAuth-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 92F0DCFFD953EC71FCFDB3666D6EA0F4 /* FirebaseAuth-dummy.m */; }; + 5ED0F1610C2E873A4841325B13410A34 /* FIRTwitterAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AECB71732ABD8587D9BB4DE4FD97046 /* FIRTwitterAuthCredential.m */; }; + 5ED7826DB2ED8CC4DE095524E20ECF86 /* FSRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 64FDB8B8A3BAEE7F4E9AF31419F79891 /* FSRWebSocket.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5EE6BE4642CFB50AB022550D59AFEDDC /* env_posix_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = ED1556AF5E4C2B9B1D3F5307AB569547 /* env_posix_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5F1708B7AD0687C2BF83B069E0774CD1 /* FIRStorageUploadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 85963F5A5D4793A9C69D9C6A48407761 /* FIRStorageUploadTask.m */; }; + 5F4C28625699791344FBFC6808A9BDE8 /* FTupleTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C7B84BCD12457E28D8C0A6D55563C32 /* FTupleTransaction.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5FF453EA030631028E30C6BC3D4C4DEE /* FIRInstallationsLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E8EE1DCB09BF77593099C551FC273C /* FIRInstallationsLogger.m */; }; + 5FF6349B500664F4390C8FACE38B8A04 /* FOperationSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 01B5588E52D3B11F82A0D7F0C8DDAF9F /* FOperationSource.m */; }; + 604950F7EBBE3555711A5B61F54A4269 /* da.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A068D9D7C318C3DEDB62F09C48DF6E09 /* da.lproj */; }; + 60E586EEBCC6FFFA26741B26230488BB /* GULLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = C932FA22B4630537177123F6782EFBC2 /* GULLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6116CA8A83772FCBA115BACC671E5576 /* FIRStorageConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B85E94CC4133DE93C8AB2185EB576E2 /* FIRStorageConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61409E53AF384794ACAF6872282AE7A1 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF42C313DED2C3D2F5F3C5156B732A6 /* FIRLibrary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 617968B11188B95B6117BE9A51BCC2F7 /* OIDErrorUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 75E656E2ACA0B8C607F571F7D16128A5 /* OIDErrorUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 61813886EC69B09E5A4852CBA4CF992C /* FIRStorageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EB72BA1B95C57CA801DFED265DFC13D2 /* FIRStorageUtils.m */; }; + 61A8C7416EC603B14526A238BB685B27 /* FIRPhoneMultiFactorInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = B59BE61A40373B7371A718989F31D704 /* FIRPhoneMultiFactorInfo.m */; }; + 61D67B5C333F80E824E37DF5BFF079C5 /* FIRSecureTokenService.m in Sources */ = {isa = PBXBuildFile; fileRef = 31C485AEEEEE2964C83DDD0480C6592E /* FIRSecureTokenService.m */; }; + 621138AF31CC70B47190D5008ACC1F11 /* FIRSetAccountInfoRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 605F66FBD87C009EECDEEFB5EFD3BACD /* FIRSetAccountInfoRequest.m */; }; + 622D6A2CABAF936EA29F518048A1AB4B /* FIRStorageUpdateMetadataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = A29139C652B1A548F84E6EFC698953C4 /* FIRStorageUpdateMetadataTask.m */; }; + 6230A2FA25019907339AB7E5DFEDD58C /* GTMAppAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDEEB8A7411C302E9837483C2298F14 /* GTMAppAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6233EF529A762C75DC0B230BB1172D57 /* GDTCORDataFuture.m in Sources */ = {isa = PBXBuildFile; fileRef = C1F6B850C4D596D278B785A539B55B1E /* GDTCORDataFuture.m */; }; + 623E683BCDF87C8235F320291CABBCFA /* FUIStaticContentTableViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F6BF72CB8650A8FFE6D0E969D4AF6B9 /* FUIStaticContentTableViewManager.m */; }; + 6242CAEC2F8E2C0BEE8171BDD7624E85 /* FRepoManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2639674FFC61B91B6BC5DF9392EBF3DD /* FRepoManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 624C42CFD7FA7048F3DE883B44C04D60 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C79891D26C39DACEE62796D724DBFCE /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 62EE53917282ACE3FCA59F74D29416E4 /* FIRGoogleAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = A99400EE0057F9ADD1A81323F1926953 /* FIRGoogleAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6345F9F23523FC2511CBA173E98C25CD /* FIRDataSnapshot_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = EAB5C1025B15D6E3DC47C7BB0A984BC3 /* FIRDataSnapshot_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 63C9EAD131C3189391781DFAE115283F /* es-MX.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 77EC7724051F1C393F7400C9463218FA /* es-MX.lproj */; }; + 63DFCFABEDE5F4FC6AA3555B6CA650BC /* FWriteTree.m in Sources */ = {isa = PBXBuildFile; fileRef = AF8A2024FCA85F80B0E6A5BE255D7504 /* FWriteTree.m */; }; + 640209D1D7B24B1AA144E731BFBE6D66 /* FImmutableSortedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A56F42E97685ECB4B0F45C2EAE622DBB /* FImmutableSortedSet.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6435AA398ABD7022725DC4180278829F /* pb_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 792D76D6241F70B08F7CAD7ADB1D72E2 /* pb_decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 648DB2FD4628E41C81C4D2CCE0C47202 /* es-DO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 74A4644D82340D84377819E6EFA115CC /* es-DO.lproj */; }; + 649A64FB86B5C688F3F9A27628A2F0D1 /* FChildrenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = A99C7A8E7DC4E7B780CCBF06E6C3EF8A /* FChildrenNode.m */; }; + 64D095CF8F5478D78FD4DEBED5A308F1 /* FIRAdditionalUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4006509B9A0C604BC5178AD2B58C0FCD /* FIRAdditionalUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 64E4272B0D45B5F9815226F5E10394D0 /* es-SV.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 49F63393A9E80EBBF65F56B5EDB54614 /* es-SV.lproj */; }; + 6529D12FE40EDF6AC2319ABA3F5680EA /* GDTCORClock.m in Sources */ = {isa = PBXBuildFile; fileRef = 9646F23A0D4521DB88A49AE6ABD164D8 /* GDTCORClock.m */; }; + 65435736A0268A60A120077901928565 /* FIRAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = F0E73FA2D08DB50ACE6FA0819B438E5D /* FIRAuthCredential.m */; }; + 65E794BF0EB93249952535E25AAD7555 /* ic_account_circle.png in Resources */ = {isa = PBXBuildFile; fileRef = 70582D78CBEA51C33A8B82C9FFB723B1 /* ic_account_circle.png */; }; + 660DC62495C43FFE4D5D1AC2657F8FED /* FIRStorageGetDownloadURLTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 218384F9184D07D0CC75E9E2D849833E /* FIRStorageGetDownloadURLTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 661A9FABF43DBB4D57FD56A5F200D595 /* FIRAuthBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = FA08C3D52F16A1EC004CAC114EAB689F /* FIRAuthBackend.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 662B0A41D8F32A4659A1334E84B702E1 /* GDTCORTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = FA139674819FBA9C94F5375AC3D9C06D /* GDTCORTransport.m */; }; + 6646F7A9030D70C4019BB2316CF337C8 /* GDTCORDataFuture.h in Headers */ = {isa = PBXBuildFile; fileRef = C47465A0B2EB8E8D479EAC036DD13898 /* GDTCORDataFuture.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 665CE8BAE7485D20C42A1C8B79B49E0E /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D5B40554AE06250C3560A070E872FD2 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 66ADA981F5A6DB6091A81989463F261A /* c.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7EBE8D30CFE961F27D4DCEF388590C8C /* c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 66BD54F510355737D99703E4AB1A7BC1 /* NSData+FIRBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = 14FE6A4FB9D07E0668CC728919204386 /* NSData+FIRBase64.m */; }; + 66C580838368369BE0956947ED4BAC81 /* FIRAuthAppCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = AF35B0BD464B5D45C6B66A9A600F74F5 /* FIRAuthAppCredential.m */; }; + 66D679B90F1CA345F347E6E776B4983E /* FUIAuthTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 573253504667D85EE768C19D3F939A99 /* FUIAuthTableViewCell.xib */; }; + 670E2A31490D13725DFB5CBBF08B12EF /* OIDAuthState+IOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 16B53E64756CED682CA2F191367C5A91 /* OIDAuthState+IOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 67254C5431E7C798A079AC142A3F3978 /* FSyncPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E16797E9464DC13C0026A832D0C8518 /* FSyncPoint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 675438E67A29A8C44DACDCCB3068394D /* FIRAuthOperationType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E741077ED9CDA63CB0EE1E4387BB7B8 /* FIRAuthOperationType.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 682F84413FB7860856BDFE2284F3CA5D /* FSnapshotUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 865D3B59B3F895B75DB12A7B67131BB3 /* FSnapshotUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6868432FB3D97578C24EBD4B94D3D8D3 /* GTMOAuth2KeychainCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 1298FE36D6175255C29C7661A7C10629 /* GTMOAuth2KeychainCompatibility.m */; }; + 6872C9725C60CDB8B44A961B40B6ED66 /* Pods-MyExperiences-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D4B1169E73887E37BA13394C51E86E9D /* Pods-MyExperiences-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 687FA8E493C93E1802D575740872F443 /* FIRSignUpNewUserResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 9532DBD2E25AE8B4F16B588047B3C540 /* FIRSignUpNewUserResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 68DA1592ADD50C6018446F171DBF70F2 /* windows_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C634386C4AF3FD1EBC5CEFEF84C46AC /* windows_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 69148E8F738D51175109D84DEF186D1D /* FIRCoreDiagnosticsInterop.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B507101B953E5884032D7D3E1792371 /* FIRCoreDiagnosticsInterop.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69BBE3F9F46DF14F6EC457ED81AE0615 /* GULNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D30EF1C0685DD064607D8AC309AB8FE /* GULNSData+zlib.m */; }; + 69DAAD8FA321803E471DD0865A3EA960 /* kn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3795D22043104C7331249E54D65FDCBD /* kn.lproj */; }; + 69EAB586BDAEE273C8BE3D2290CEFF9D /* fa.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F00352F26052169EBFD33F59ECAD552D /* fa.lproj */; }; + 69EF791CC8EBAAD9AAF671EF3C5C2ACD /* en-SG.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9D340BECB137147E09B0C0BDB14FCC42 /* en-SG.lproj */; }; + 6A019FDF340EF64A0CCABFE6BE7C706B /* FIRStorageMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 2BED935E00DCA51EE1CBD631ED2DE24E /* FIRStorageMetadata.m */; }; + 6A1FD1AC578C58BC8A617A0A8606DDF0 /* FIRStorageComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = BF2AEE9791F5228164E2A159B584198C /* FIRStorageComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6A3D3A3AEFF0668302A0FF4CAB1F6554 /* FIRAuthProtoStartMFAPhoneResponseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 65CB8A235F0A6036357C260E72FF4F51 /* FIRAuthProtoStartMFAPhoneResponseInfo.m */; }; + 6AA90E0D3A5FA0045509804BD80D0C9A /* FIRVerifyCustomTokenResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EEC83A35CA914EF24F3A4863B5C2EA9 /* FIRVerifyCustomTokenResponse.m */; }; + 6AAFBCBD61515508338F589D69E75603 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B31CEFCCA8222DE30CE0A3C9C1694A1B /* it.lproj */; }; + 6B2C401E08F2AC0A87453061CA3E8E2C /* OIDAuthState.h in Headers */ = {isa = PBXBuildFile; fileRef = CA3DE504B14BEEF56B3ABB1C443B66D5 /* OIDAuthState.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6B51E4E5D5B08C3E33B06C2AFAC81B01 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 6B730668021CE3D559888CE8397D4298 /* FIRMutableData.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AEE4F8D71B44E0B56E0871B80A32DEC /* FIRMutableData.m */; }; + 6B804CAA8F736BFF23D62A9E41822E58 /* FIRMultiFactorSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A1199F3B6D178FFC9022E990B57BF88D /* FIRMultiFactorSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6BA4B719CEB0771364DE59B2AB00CEE0 /* env.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3D67CC9E38C38BB28F7D6453E84A0E1B /* env.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6BAC35A35D56780297767C0649A0D9C2 /* zh-Hans.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0E2FDE1552CDE29E8BEE17FA5D661B3B /* zh-Hans.lproj */; }; + 6BD6462A74CEEC599377E3D62409302D /* fr-CH.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 42F6E008885453176BC7D27CA366F6C1 /* fr-CH.lproj */; }; + 6C0AEF276EA423B89B7E093D861FCE39 /* FPendingPut.h in Headers */ = {isa = PBXBuildFile; fileRef = D2DEEA5B92D2B175ECEDC2E2557D596A /* FPendingPut.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6C0AFAD79936BB20A4998D1ABC80DE6F /* FIROptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FD82FD67806944740A8EA55D55E725D /* FIROptions.m */; }; + 6C18E9EE8933E2363D16600DECF70A8D /* en-AU.lproj in Resources */ = {isa = PBXBuildFile; fileRef = D532471374ECD1325BAAA8585722C50E /* en-AU.lproj */; }; + 6C254C11330DAC6125A3DDC7021EDB54 /* FIRDiagnosticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C32CD26CE098C26904AAD088DBBA4C6 /* FIRDiagnosticsData.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6C46F55B8A09E4587FEEC04354F2D2C5 /* GDTCORAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = A3E2C01DD82DC9DFC1C6679BEB9F35E1 /* GDTCORAssert.m */; }; + 6C89DB341AA1CA45037B037568C6761B /* FIRVerifyAssertionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 667D98F84E5FDD3D4D026D657ABB2756 /* FIRVerifyAssertionResponse.m */; }; + 6C98BABC3A75D5EF8C3371D2599EDFD0 /* port_example.h in Headers */ = {isa = PBXBuildFile; fileRef = 787252786CD85DC82A24166F78BD4E85 /* port_example.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6CA6A37312446FC1D71B5C60725F849C /* FOverwrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C90A57F312058F5070F24619DF2D4AC /* FOverwrite.m */; }; + 6CC2C80D1CEB68F1B21A99AC2ECA6386 /* FIRSignInWithGameCenterResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = BE847A5DCB4BFC93207699CCE355AD02 /* FIRSignInWithGameCenterResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6CC40BF6B603E35E518995A1934FF24F /* FTrackedQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = A526C31FD98918B4CE3A59BB0BD27C90 /* FTrackedQuery.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6D3EDAD808408B202C2E25BE168E42EC /* FIRConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 493BF9F147B5C3D81A03760D93753452 /* FIRConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DAEE1BB6C23773E0DE8D248A93D826A /* FIRAuthProtoMFAEnrollment.h in Headers */ = {isa = PBXBuildFile; fileRef = 75FAA3E93E73C340192C7B4B9471389B /* FIRAuthProtoMFAEnrollment.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6DF3B0AAA63BEAFCE7094FB577489D3F /* GDTCOREventTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F7D6DB45BC5F0FC8039D5B4B9655B28 /* GDTCOREventTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E0626DD94F11FB7668DE2838F52D9E8 /* FUIAccountSettingsOperationSignOut.m in Sources */ = {isa = PBXBuildFile; fileRef = 371F7C2003CB9DDACB528B7500A18ECB /* FUIAccountSettingsOperationSignOut.m */; }; + 6E07C8DFE37BA80FD964E87D12C64358 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 331D5AAD7CCB53498DF832B15B48EB0B /* FIRErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6E7F9E6163F85ACCA9353B5573B1A9CD /* FirebaseAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = AAF1F950FB05508CDC5E0BADE1A27F22 /* FirebaseAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6EA78EE3630B21318D3441D1B0D8AB7B /* hi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 331968F42465E8E681660A4F9DE033FF /* hi.lproj */; }; + 6EACA84AA4C94A8969D1A7F8A9FF7E06 /* nl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F156EBA03AB88203E99DFE8B8BA46A02 /* nl.lproj */; }; + 6F4FAEA776D76A65BCB083D627CC06CE /* FIRInstallationsErrorUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = C18E3D1267F99711A68A8B02BF9FFDD7 /* FIRInstallationsErrorUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6F62B2A2A17D5EA43DD35514513722AE /* FIRResetPasswordRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A7842D8719CBBA97D03A9F7A3133A20B /* FIRResetPasswordRequest.m */; }; + 6F75FA17DEFB5467875B879FD6EE565D /* FViewProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E0A008BCE52F3A0574E15041D57A2CC /* FViewProcessor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6F8340EF98B0A00DDBAC8D01A80C8A1B /* coding.h in Headers */ = {isa = PBXBuildFile; fileRef = A270BC478BF1E34A0FFDEE765533F5D3 /* coding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6F85AF013E91F455A3A1590151915C4D /* GTMSessionFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 654BB45670AA13C68A7FBDF787179FBF /* GTMSessionFetcher.m */; }; + 6F969D63E1984AA64325C08C49EBE9B3 /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A78967BAA83809158FF45AD8D7E55402 /* FIRInstallationsItem+RegisterInstallationAPI.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6FD2F3431F03D1A5C3DE8F1D802A983B /* GDTCORConsoleLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = CFF7FA3C082DDECFA0AAD760E36D8078 /* GDTCORConsoleLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 700E999A99823729FE3C1D4F03B17980 /* PromisesObjC-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E645CD0A247B7C65BC6B8E58799DDC /* PromisesObjC-dummy.m */; }; + 702101ECFF609503A6F8701ED8ED700A /* FKeepSyncedEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 54A0D35E86F62F0B4BD48A8412384F5A /* FKeepSyncedEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 704250AF1BC03587E0B7EC6DEFD83408 /* FIRAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = 9263934336E5BCC5C8C49D503E09B471 /* FIRAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 705E22C52493D0AEDE135873802B54E0 /* OIDScopes.m in Sources */ = {isa = PBXBuildFile; fileRef = A63980E1EAF8FC62A63C8A59A8AB6541 /* OIDScopes.m */; }; + 706FCF28C3D142E7E95B9A8D82E777EE /* FConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D2614520CA43EA86616C7D7EF35F49E9 /* FConstants.m */; }; + 70978C3161999C402AC8ABD8DADF720A /* FTypedefs_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 477B26F19AC7827CEAF7052AEAF4F1D1 /* FTypedefs_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 70B9A0900CDBA80EEBE38C19F10D287C /* FBLPromise+Always.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB47C109880284CCAC55AF2BD005BFB /* FBLPromise+Always.m */; }; + 70C33E6E27C972FE599B8A3E4FB5DB2C /* tr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0DF00E0B4050F287AF4F7EF1D9D3520D /* tr.lproj */; }; + 710C7C342D9B884A57B31554A8301D3A /* tr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F4CAD44EEAACE1ED06ACA9EE0BA5A69A /* tr.lproj */; }; + 719D3EE29ED9ABD723896802B2E3540E /* table_cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = D7918CAF17ADB04CA0D829A49A5E2583 /* table_cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 71BCEC30B9A618753E543ED8C606B9F8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 71F2B0C6705011C5B69F3862002A8514 /* FIRAuthBackend+MultiFactor.m in Sources */ = {isa = PBXBuildFile; fileRef = 6015A44958D8FCFD5AC5DD46D28EA3CB /* FIRAuthBackend+MultiFactor.m */; }; + 72551A633B093070277BBF1D8EAB7F8C /* db.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC5AD85024AEFCE15D5BB20FF5DE604 /* db.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72AFF5873D7E384F2CFBCF8F03E56FB0 /* FTupleStringNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 838C87E3EEC318432FFA15251F58F8F9 /* FTupleStringNode.m */; }; + 72EFC9D90E0D66ACD54150B700EB5191 /* env.h in Headers */ = {isa = PBXBuildFile; fileRef = 636F5649D4AEAEE24280A6B1209EADFC /* env.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 731319FF83413B389A0C20B2EC7CD6DA /* es-GT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4A4CBF036EE62FFEBB150AB9227C0939 /* es-GT.lproj */; }; + 736F02A4A427A481427A3C8465EBB3AF /* FIRVerifyCustomTokenRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = ACB1AD1F6F42BF9BB16AE8500CEB3DA7 /* FIRVerifyCustomTokenRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 738C1C16A1A5959F3CFB28472DE51A70 /* GULHeartbeatDateStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = CFD98378F7C00DB91E8F99CDD3B231A9 /* GULHeartbeatDateStorage.m */; }; + 7395D8250077260C4CBA38A6C71FB221 /* FIRAuthAppCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = F8FA12F53A842731E91E4E2D261613DD /* FIRAuthAppCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 74041B150381C862CFE3B7A05F7026EB /* FIRSecureTokenResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = E9D51A261F16AF25D0F6D395165163D6 /* FIRSecureTokenResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 74572409E7AE0C42D50E525EDF7E970C /* FAckUserWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = C35B22038D2BC9F2DD0326DB7D408CD9 /* FAckUserWrite.m */; }; + 7468A23BA7000985D721A7C11A520985 /* log_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = AAA93E7250E2606BC3CE32C1BCD11A51 /* log_reader.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7489186AFC0AB8169E96232277138495 /* es-VE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 68E6D55D2E5797DAEE6966BAFCF95C5F /* es-VE.lproj */; }; + 74AAF0FA912E952CC3296CB18DECF8F0 /* FTuplePathValue.m in Sources */ = {isa = PBXBuildFile; fileRef = CC316F2270A94C0F8B764AC4D6CE36E7 /* FTuplePathValue.m */; }; + 74CCB49825E488983AB3A0C14E885DC8 /* FIRVerifyPasswordResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CD154F70A82503F71907F09DA04D6A82 /* FIRVerifyPasswordResponse.m */; }; + 750B820E8FB644D1C6C858F716DF0D94 /* FWriteTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 62C87D6A9A8CBCDE954AE13FC94E21EF /* FWriteTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7523A1FFBB9A4AD52DB947BFBFB95A9E /* FTupleCallbackStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 113E302B441B981A827DD3B4EF35419F /* FTupleCallbackStatus.m */; }; + 7540C69AC8A0C763556FB85A18AE1AE7 /* GTMSessionFetcherLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = D6E3C4C5F3AD43FEBF6E81A4964001A8 /* GTMSessionFetcherLogging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7550AC1065D21D0F055B71D60963A6CB /* bn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 03F04BE92A78E9CB93B09F492E85AAF1 /* bn.lproj */; }; + 75CDB4E7399EC92E06E5575AF06A0492 /* FIRVerifyPhoneNumberResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C4908AAA89E23228B4BAE39DC3B770 /* FIRVerifyPhoneNumberResponse.m */; }; + 76015C6D9A72F2B002CE9A33C1F78D8D /* FUIAuthTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 7082B9449622F069DA6D80470872D467 /* FUIAuthTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 761AB4CEB901338477D75C8B9177B5DF /* es-BO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 6B74182157734B3092D8EFAF015E4B26 /* es-BO.lproj */; }; + 76282547D1A0FCBB793D803F330BCCF1 /* es-EC.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 40F945E679A09218AE09F90EED9F4FA2 /* es-EC.lproj */; }; + 764E0FA79B2BBF1DF354D625FF25587A /* FIRDeleteAccountRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D9E2521795EDDB2463612C8580708673 /* FIRDeleteAccountRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 767179F60EF92DCEFE95807F8290C68E /* FIRGetOOBConfirmationCodeResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EE3073A02E48ADF059D298867A4902 /* FIRGetOOBConfirmationCodeResponse.m */; }; + 76C8D5115AE00C059DEB289AE147B7F3 /* FUIAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 35A44EC21C676A28BC2A89DDC04107F9 /* FUIAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77022DA37144CD3FBE165FCEE8C5277F /* FUIPrivacyAndTermsOfServiceView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A7DC61A346E675EE6ABAE77C84599E6 /* FUIPrivacyAndTermsOfServiceView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7706DB609947D90EA4FE368F97C453B6 /* FIRDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = F379CEF3D2BB9681071028E02F1BD578 /* FIRDatabase.m */; }; + 7725AD47580F7EC6D4D36655133F9E78 /* GULReachabilityChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA61BB6DA2B3B8637F8722F9AA18F5F /* GULReachabilityChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 775E22843AD00704F6C417DDA74CF096 /* FIRStorageObservableTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FD4FE57FB9B916510FB562EE2A4BE10 /* FIRStorageObservableTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 77ACB4CA3803992854F1A1B0DE0190A6 /* FBLPromises.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4900DB7C20F8911744B754D0004709A8 /* FBLPromises.h */; }; + 77B2042023799E1A5CCE2817D26EDDC9 /* FEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 38C591D4DAB923A59C4FB29164568937 /* FEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 77DC9D2249F6CADFA28FEBC37987F41F /* FIRFinalizeMFASignInRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A29EA43E4DC3B153192A8339CC174C3E /* FIRFinalizeMFASignInRequest.m */; }; + 77F28402B8827D867A747BCEE3668886 /* dbformat.cc in Sources */ = {isa = PBXBuildFile; fileRef = 855E8833CCE10619B411301B970C1A9F /* dbformat.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7800B47B67A815BE2E4DCB87A1E22D43 /* FIRStorageTaskSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = B54C585EF7038D6E900107B27C41362B /* FIRStorageTaskSnapshot.m */; }; + 79117048A3C4F245532CAE57EE37901A /* OIDExternalUserAgentIOSCustomBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79E78D7503509C5FB9CECC26794CC1 /* OIDExternalUserAgentIOSCustomBrowser.m */; }; + 7949AE3627B387000F5A1B35762EB4FA /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 5119B34C2C5AA2AE16AE4B3BA48C5532 /* pb_common.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc -fno-objc-arc"; }; }; + 794A28D942D682A8EB90588F63F3709D /* en-CA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = AF07CF05D98104373FD3D96B8260E436 /* en-CA.lproj */; }; + 794F295EC59C4560E6CCD03EEDA8B66A /* slice.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BF58E7BD20A582ADA2FE78D5B00B44D /* slice.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 79D8009BEBE725189259C7A9A5EF99C1 /* iterator_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = EEF97A03248B0CEB94C0A83B2825E8E2 /* iterator_wrapper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 79F4E4CA1B6A818B370FEB69AA09B4FD /* log_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = A6D4918D8DF4FD0507640613DA81CC4B /* log_reader.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7A08D3E6A57D1770548899295DA8D974 /* FTupleUserCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 24C6B81A862144EBBB10A29A617297D3 /* FTupleUserCallback.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7A50620B4C214D8B10974690FAA364CC /* GoogleDataTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0318A5FEF1987622B3803E57493B9BD9 /* GoogleDataTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7AB0F39B04F5C0445C3262C0A3CE7C76 /* FIRInstallationsIIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B6A09B272C1AF4BC48955E6BB468C5 /* FIRInstallationsIIDStore.m */; }; + 7ACD06125D4ECC1EC05EAF68B2DC0C99 /* OIDScopeUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 77CA828E70063B77546CDEF7F69497FF /* OIDScopeUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7ADDC41744D0F3D3D3F019753E17E80F /* es-CR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A672DD638BC3C2D318FB66F0D7E6C1F9 /* es-CR.lproj */; }; + 7AF9EB305B880930B06D0711FB8DB6A0 /* FIndexedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C9657B10159A1EF60ADA1CA1B6C1E71 /* FIndexedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7B05D8EC8EE0653843D71EC1BD465CA9 /* block_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = F28F293116C24E8DF57B232A6D217EBF /* block_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7B2A3DF21F15EF978C1906EA1441C2D7 /* version_edit.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6097D15BF93E3419D955BD573255BC7B /* version_edit.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7B44B7901BDF3803A6C25612D5EC5901 /* zh.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A2FB2B9B3D118E4042071207EAD6153F /* zh.lproj */; }; + 7BEECC8EA66D8C0860DC8138AF2693B0 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86785462374CEE6C2A26DF27723AFD08 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7C1811FD8E7629E7D45AD8F41E699810 /* FIRVerifyClientResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = F998DA016600AADC4C4757203652294C /* FIRVerifyClientResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7CC2DBD8DD15F59B675BB57E34AFDBD6 /* FConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9D467DDC47ABB6AB58578D530578AB /* FConnection.m */; }; + 7CCB435518D2A10F1651D67BC5A7867B /* GULReachabilityMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 24A357EADAA35A7EF0EA56AA88103251 /* GULReachabilityMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7D3E5684CA18BBF420A6894CF3B9CBF4 /* FUIAuthErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 6301E5CDD1DED7CBC74026B7B30735C4 /* FUIAuthErrors.m */; }; + 7D8C312EF1995BFD5FC26E164E36D9D0 /* FSparseSnapshotTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FFE94EC5AF860B62041D69B5EE9486A /* FSparseSnapshotTree.m */; }; + 7DF36ADB94EDF3053487FC003C8EAFCD /* FIRStorageReference_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 278BB3E5433817C52237810200BD9406 /* FIRStorageReference_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7DFB5C1B35041DF23880D96130900E54 /* GULAppEnvironmentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 634E60D54FACAEA3CDD23BC456EB97E0 /* GULAppEnvironmentUtil.m */; }; + 7E4C3FFB907CB2E01C3F5411EE2D08C6 /* en-ZA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9CED810C143F8723E760A6F7C2DA34C2 /* en-ZA.lproj */; }; + 7E655E800382E28747E61BD3DD084D7A /* he.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 37C9A4444EFAAC11218633CD24F8D1DB /* he.lproj */; }; + 7E6CA1344E04CD3082D8EDAD07F61FEE /* FUIAuth_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC4C5100114EE4AD832B2C059B9B0B9B /* FUIAuth_Internal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E9873432C68540736211646DBBC7A4B /* FIRDatabaseConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FC53C97C18D26AB932C5045350269D /* FIRDatabaseConfig.m */; }; + 7EE8C19AA1A52012EEE0EB873A93F753 /* block.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D83D6764BFFF792BDF8BCD6FA8DC76 /* block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7F3E2C3C973EA28110FE842E83B94077 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = BF78F6F7E220218B75FDE0FF75690CAA /* logging.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7F7C4D96D09CD3201C620DF6E65110BD /* FIRAuth_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E3007F6BD5E438E138650DDACCAA423 /* FIRAuth_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7F8376D906B43A78D50E1ECB7214F2DD /* FQueryParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CDD262BE955BCCD50139C26B4E1B37C /* FQueryParams.m */; }; + 7F8CDE565E023F5CC2C0861C6D98AD26 /* FIRStorageObservableTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CFBC168B85EA71F74E6C24C03FDCA9D /* FIRStorageObservableTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7F99CC65F3BC049F4DD035F3B1E25121 /* FIRInstallationsIIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = AA58215224CE0D047281492EBBA3216C /* FIRInstallationsIIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7FA3CADD2A8C6334A62A46877ADED780 /* FIRAuthProtoMFAEnrollment.m in Sources */ = {isa = PBXBuildFile; fileRef = CC289465F3C72999640A1007EB3AB692 /* FIRAuthProtoMFAEnrollment.m */; }; + 7FB2D7E84CB375FE19E2503809D8DE30 /* es-419.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1A2746E30564EC71904AB662184CD169 /* es-419.lproj */; }; + 80000D72EB8E257326A757521C8DBBF6 /* GTMSessionUploadFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 7553C3CCF22589D84A1833B82BD7B112 /* GTMSessionUploadFetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 800FC1C96FB62CA6443CC1CBB79BC8CE /* FTreeSortedDictionaryEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 406E73A9D34FD1FB8B07E30E058567AF /* FTreeSortedDictionaryEnumerator.m */; }; + 8015D4C80CC0A099F478E42BFEAE3B95 /* GDTCORPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 622905E4C7B48388FBFAEB5B4885A636 /* GDTCORPlatform.m */; }; + 801D474941125FE5C96D1F5DECAF76C4 /* FImmutableSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 73A677A14C9FC931B5AD7E2C51F74A91 /* FImmutableSortedDictionary.m */; }; + 804A48A974F3E7EA43E120E1716087E3 /* histogram.h in Headers */ = {isa = PBXBuildFile; fileRef = 70F7778B9B8E61DC442DCB0479E095B5 /* histogram.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8053A04D3E94C47270DF7E20DC5C2534 /* logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CA5F3D7DC34FE7C993F9CDB4D26F4DD /* logging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8093597DAF1956ED29ACB550847FBCF4 /* en-IN.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 97031F647363FF54D7E0D14B833CB369 /* en-IN.lproj */; }; + 810080743EC879A912A46CD2835D95B4 /* GDTCCTCompressionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C75CA0EA947F458A55BC7558B99C325 /* GDTCCTCompressionHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8151568CDB335C26709AB8834673F532 /* GoogleDataTransport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D39D997779449D74727241923F8597A /* GoogleDataTransport-dummy.m */; }; + 81904A0CF058DD1046999ECE048DFCE4 /* FIRAuthDefaultUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 334EAB92C832A8B1A25E76ED920D2F60 /* FIRAuthDefaultUIDelegate.m */; }; + 81C45B1D2021093BAA0D8E848822C0BE /* FUIPasswordTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D46BE344296E1A185ACCE52FC07459CE /* FUIPasswordTableViewCell.xib */; }; + 81F22F8E4759DD80E1AB340B47F7EEFB /* GTMAppAuthFetcherAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B8DBE56121715EE74A27E96DF805741 /* GTMAppAuthFetcherAuthorization.m */; }; + 81FCC5CC0FBD4AC46B1A3F46DA227E2E /* FIRStorageTokenAuthorizer.m in Sources */ = {isa = PBXBuildFile; fileRef = F036049EC79DBAF2E473B1A9F7BF8D11 /* FIRStorageTokenAuthorizer.m */; }; + 8218B58842B931482D288F9C179C1C4A /* es-419.lproj in Resources */ = {isa = PBXBuildFile; fileRef = D6AB56177AAFE39BC48DAAC32ACCF3E3 /* es-419.lproj */; }; + 823C53D54E74E675B01DF082CFD5F984 /* arena.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C3CA4F92C08777AF6CB0CC107100639 /* arena.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 82456F2CA6BED1E98367781FA0B98956 /* FBLPromise+Timeout.m in Sources */ = {isa = PBXBuildFile; fileRef = E4F2A464610BC0BCA8327F2EFD71673D /* FBLPromise+Timeout.m */; }; + 82E90DE19021BDAE4572B74D3F7823F2 /* filter_block.cc in Sources */ = {isa = PBXBuildFile; fileRef = B52ECB24B1A93B2993DBF10DE2DA98B5 /* filter_block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 830093FBA220D68767E42280F8AEC9A1 /* FLimitedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 710C93802B6DFF2AC35E8AA400C51F01 /* FLimitedFilter.m */; }; + 831019A506E1CFE8A7BDA4712278555F /* FIRMultiFactorInfo+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BF69E8882B8B2DB954A2A48042B84CF /* FIRMultiFactorInfo+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 835909BCD28432E37FB3C537EFA3DF2D /* FIRAuthProtoStartMFAPhoneResponseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E8697049410C51707EB215F2B6E1EEF7 /* FIRAuthProtoStartMFAPhoneResponseInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 83AAF2332D14B045119D1243039D97AE /* ro.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 64948C59CFBEBBCAC0EE75768B1A66F7 /* ro.lproj */; }; + 83B513BCA178F00372FF0042E59A1759 /* GDTCORLifecycle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BFCFAAC8BFE82A214A763FFC468F8C1 /* GDTCORLifecycle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83BAF0108579702991C01C961439111A /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC596C717FC35E61C792FFD5B68DCDE /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83F5625E3BBFAFC6F6E1C6EA7A516C6B /* fr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9F19F2DAB2BE2733FD82D447F48A654C /* fr.lproj */; }; + 8416D140B256BD069CB602D6204A3850 /* FValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB5A9CB8FC820368415F100A55EF934B /* FValidation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8417CFCEA12E96E62CFA4A646672BCCB /* OIDServiceDiscovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FB936E76A9A8C28FD4C57098BA48A88 /* OIDServiceDiscovery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 843D250BE5DB0C04925A5E9B15062E5E /* FIRFacebookAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = BAAEF18BC7684AEDE7B7A4B4E04FB187 /* FIRFacebookAuthProvider.m */; }; + 8461186C4A4FEB64043D673E667F694F /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = A9FA51204A20C57FD2FB2EFDBFFE3B61 /* FIRLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 84767001BF9038BAF82C200D383B33FA /* FCacheNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B82EF8025DA0FBD0188AD9F091FBB70 /* FCacheNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 848D22C317E754C83F8B7747E07CB1C1 /* GTMSessionFetcher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC8863CD88E6BCE4F75A47B49C31FA /* GTMSessionFetcher.framework */; }; + 84C9CC4035AC423C9CC0DEF3EF0679A1 /* FBLPromise+Any.h in Headers */ = {isa = PBXBuildFile; fileRef = C499E907E739C12D9058162F8970BAEF /* FBLPromise+Any.h */; }; + 84CDE1F911578AA4554F1C68B6E23836 /* GDTCORFlatFileStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = F3DF5AF9462B5AC7A7232B374178407B /* GDTCORFlatFileStorage.m */; }; + 84E0CA1241B5287B56CB5E57DC56708B /* FirebaseDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CC90D6F4005C5FBF64F12F2C50BA755 /* FirebaseDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 851880D13DB5D1A93358B1F2AAE060B6 /* FIRStorageMetadata_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5AD0170E1AE017F7BF65280EE7A9D1B5 /* FIRStorageMetadata_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 85248DFD6E24F10D401BBB6280DCDF80 /* FIROAuthCredential_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C0C49B9FD1D38A300F17C741E09F97 /* FIROAuthCredential_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8526FCBCB65A3883DFE1141FB16322BA /* FNamedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3785DF72C6DCAF47AE366F2829ABEDF0 /* FNamedNode.m */; }; + 852E948A27E3143355DF5787C97B7208 /* FListenComplete.m in Sources */ = {isa = PBXBuildFile; fileRef = 8469477C787E65AC4DECFB61629C330F /* FListenComplete.m */; }; + 8541D6C082F7B93111E7AD288B3B87EF /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B49E6C76268B31F8E5AB9787C649111 /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 855E190D93345AF7543B5E878CFA70D0 /* FIRGoogleAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C6EF5A4DB9F566411010DC8177A31C8 /* FIRGoogleAuthProvider.m */; }; + 85AC70140CF3718AA932C21689BF865A /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 924E549ABA7E7BBBCFAC5E46CA17885C /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 85B5CF9BA2ABD15512ED5E2FBC1773C2 /* FIRWithdrawMFAResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D1C280352A1F5631E02957E16C08DD7 /* FIRWithdrawMFAResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 85D57991CAAA620C3BCAE98FFC6D4BC2 /* sr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 796D52C9F909C41144190320EC3D42ED /* sr.lproj */; }; + 85F2CC4C6E1D8F5AA03361800F3A0C8A /* FBLPromise+Catch.h in Headers */ = {isa = PBXBuildFile; fileRef = E62BA6BBCD5F0BB2FCD80BEF9750D13D /* FBLPromise+Catch.h */; }; + 865C483FCC318872145D059693ECF655 /* FUIAuthErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C8819DA241A028BAD9315C60199BE863 /* FUIAuthErrorUtils.m */; }; + 86634D0E28C70C490B41AD0A80F708D6 /* lt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9B5DAA4FAAD2341569C841186C84AB46 /* lt.lproj */; }; + 86C6E9D09DD9A2F765ED9CF5F981560C /* OIDURLSessionProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0492AB09814CBF428CF9310A7DF7BD /* OIDURLSessionProvider.m */; }; + 877BD505C3FE6A491E1F517FFDB7F9B0 /* FTupleRemovedQueriesEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F78C92980B846317529AEE3CAF792AA /* FTupleRemovedQueriesEvents.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 877EDB3BD268CDD6D4A1434B65A21FF1 /* FIRDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = B2D180E7D85A1EFB4F921E0D6C62060B /* FIRDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 87DE0FCA6D20400F43E491E55C7AED1C /* FirebaseAuth-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B49FFCD7B5EBFCE7B830557C601A9F0A /* FirebaseAuth-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 87FF583960777515289BBE8EAB91D5B7 /* APLevelDB.mm in Sources */ = {isa = PBXBuildFile; fileRef = A896F717F028A846414875FFEE157568 /* APLevelDB.mm */; }; + 8812C6832F78356760DE0923F0208766 /* FIRPhoneAuthCredential_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C4D13117E55C177BC67ADD141D7A6557 /* FIRPhoneAuthCredential_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8828DCA475804194FE950AC559A9CB9B /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 81947381D2EAFE5DAE6EB80D863358BD /* FIRLibrary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 88BB134FCEB53925A505A58C1474B276 /* FIRVerifyCustomTokenResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 295D5C63FA45919B29F2B47126BA3657 /* FIRVerifyCustomTokenResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 88CCDDE369F0D57E4768BC276812D0BB /* FLLRBValueNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E8A2ED064D9D1ADB6E5DEBAD99AB7 /* FLLRBValueNode.m */; }; + 8955CA20EEA55F5D75CDE87F0CADCF83 /* OIDScopes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FBD09FC244F8C77BA89C81EB61375D1 /* OIDScopes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 896A78E7EB53DCB2813F27733F547545 /* coding.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86A61AF98CFC730742F2497D6BD3094C /* coding.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 896E8737F32EA9E5D369123FA6300C49 /* de.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 03AC94CC3669CD2F4343DCD28A98153B /* de.lproj */; }; + 89C5F6C4D72EB3EA22FCD1C29505B584 /* FIRDatabaseConfig_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = E0E399D7C90DB8709C4D6B4C695505BB /* FIRDatabaseConfig_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8A26E2B804342A3D00E6FD10D7B5FEF6 /* FKeyIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 533A075CC6706D52D274E374A6C5F9DD /* FKeyIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8A2E4C6A0316CC01B77F93A37F110FDE /* GULNetworkConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 86FBE6D4358D22E5A6431DB64E093622 /* GULNetworkConstants.m */; }; + 8A56347FABE2C135A87C8DC88DC39A2B /* FBLPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 10CEE0353BF9A5552A076306DA76AEE7 /* FBLPromise.h */; }; + 8A8B1741DD4AFEA9252A0B5FBE02CC26 /* GDTCORUploadCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = D5BC3E7F58942D74E36BDFA2CE60CE9A /* GDTCORUploadCoordinator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8ACA9C8B657C3C149214E3649860AF76 /* OIDResponseTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 156E36CC1801474606A0B980E1DF1182 /* OIDResponseTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8AF6939EC8AF2C00EB0C89ADBAFA138E /* FSnapshotUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = EB92407015693027CAA3FDAFA73D9004 /* FSnapshotUtilities.m */; }; + 8B75BDF535CA2F37FEB50CB6C5549877 /* GTMOAuth2KeychainCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 62B5C69DF77E1FC8B2CC1480BB7776A2 /* GTMOAuth2KeychainCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8B768769F2FCC80F02901B62AAF0AE2E /* FIRMultiFactorConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FDF1C00DD35EAEB9F29A29E8E1AEED7 /* FIRMultiFactorConstants.m */; }; + 8B8829DFC110B8B0D7D0A7F7FA51473B /* GDTCOREvent+GDTCCTSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = F514CF18463C2B267F4B21CE743FC308 /* GDTCOREvent+GDTCCTSupport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8C516A66D945CA04F9A532E68199C050 /* FIRSecureTokenRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 84B17AAF40781DB944D8E2218CE3D551 /* FIRSecureTokenRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8C72E8B429081346274E5A93081D1C80 /* FTupleBoolBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 866CC51076A49B7A5196DCF601092E13 /* FTupleBoolBlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8C7A0D8A352ED75BE526BC8311E6F499 /* GDTCORUploadPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = 584DB4080DC999B0DF412672F047EB69 /* GDTCORUploadPackage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8C9775088EB2BC331ED937AFFF918600 /* GDTCCTNanopbHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 54C343323DA324F133310E331A56EC54 /* GDTCCTNanopbHelpers.m */; }; + 8C9F134C7326A6EA58E8F19A477B06FA /* FTupleTSN.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7E8EFB9E99E8AAFEA96ACA4086DBE3 /* FTupleTSN.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8CADFC6D18D485950E21F6D6B7FD21DE /* FBLPromise+Then.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AB353792B56B5B30FA24FA07336722 /* FBLPromise+Then.m */; }; + 8CFFE7B6F1A89899F45DD6416CA03F40 /* en-IE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B10154179A246D8D0A16DC1C08225929 /* en-IE.lproj */; }; + 8D0CD9DB407585D44818C6904A3FB6AD /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 580A2DF400B3703EDDEE080EF2686B80 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D45E4BEC5930E087E1E2C7D02269107 /* ic_visibility.png in Resources */ = {isa = PBXBuildFile; fileRef = 310A0ABEA5C28EC185CCC6BE875BBC07 /* ic_visibility.png */; }; + 8E16D3EDB94720C597F6CD586EB5F447 /* FIRAuthGlobalWorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 55E877FAB1A07AA39659E1E33B454A34 /* FIRAuthGlobalWorkQueue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8E4A4E11F424D88C0172B4A6CD045FD3 /* FirebaseStorage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9355EE8CB9035164A79720BFC33A56ED /* FirebaseStorage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8E6B9960EC047797A00B79F62D4124C1 /* FIRAuthAppCredentialManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D469034D09270D26A090BD73BAF7BBB /* FIRAuthAppCredentialManager.m */; }; + 8E79BB8C34F8BFD02697676CF726AEE8 /* FIRStoragePath.h in Headers */ = {isa = PBXBuildFile; fileRef = B213F5865A99165D7CD215C45D137240 /* FIRStoragePath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8E830E3318E1AF2C9387E180B57C2A88 /* FBLPromiseError.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D7BA2171283849317F64AD374A314EA /* FBLPromiseError.m */; }; + 8E86DDDC4FD5A03C1A74E8A690387FC2 /* GTMReadMonitorInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 792379C88F502528FDFCFE6202E0702E /* GTMReadMonitorInputStream.m */; }; + 8E95B6FFFAC285BEE38684A4A7D8E30B /* FIRStorageTaskSnapshot_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BDDE1C8BDEA616246AD25A843C83C0B /* FIRStorageTaskSnapshot_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8EF100949FE2D45B954E1E88C95D268B /* FIRStartMFAEnrollmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = FB35D2B3E2A95345454CCC31127AFA58 /* FIRStartMFAEnrollmentRequest.m */; }; + 8EF66D6A65E0849321CB79239C8AD085 /* GDTCORTransformer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = BD266F211E48CEE436ECB2082049DFAF /* GDTCORTransformer_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8F5ADDB1B39D7E123C5F905AB86E038F /* ar.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 7FE12394BAF5BCDF91A1683D1D50C8DC /* ar.lproj */; }; + 8F99420AD42119A0A9F8CC4A4AEE9DF7 /* FIRInstallationsAPIService.m in Sources */ = {isa = PBXBuildFile; fileRef = FDBB301A94F6610BADD69F289B58408A /* FIRInstallationsAPIService.m */; }; + 8FCF84A8B634A87288A82B3087643899 /* PromisesObjC-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 27C158781A825E2584EA79FBE472E11B /* PromisesObjC-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8FF5BA052B46F52BEC64AECFC7CBE830 /* th.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 68C7EA4DCAD33358C682613FB0CDF819 /* th.lproj */; }; + 905175ED3B26032DD497D9A0F03E1023 /* FRangedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B37F5E42FA68448CE182756873C9A2CC /* FRangedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 90E7FFB1CDA02508DE000111BABF9454 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + 90F52BEB687049C2DB0139830075BC05 /* GULKeychainStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = C9F72563209A23CBD0D09F13E342C5F8 /* GULKeychainStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 911926D9525D10CE088B5472F5CE9AFF /* merger.h in Headers */ = {isa = PBXBuildFile; fileRef = 031EB143A6EDC569B9AB682402960F1A /* merger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 917C7410F4D06546F3C2ACD632669FD6 /* FIRUserMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = C21C89AC19083B376E164BCC661CB8D9 /* FIRUserMetadata.m */; }; + 918A9A673374AB623CF2307D86C15A4E /* FTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 76F463D2321280A211075F635EB82633 /* FTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 91907BA379327CACDF19EA39EAD05338 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D873F482DABA5FEA5DF77519B4A35C6 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 91AA7DB040EF94A27EE34059D7F9B621 /* FIRStorageTaskSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 38B690DCEA9427D80930EAB58024467C /* FIRStorageTaskSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 91C0BA0E9F54FE577AF208622F2482AC /* sr-Latn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B07EFDEC4F73E46667B5472E98CA5B7E /* sr-Latn.lproj */; }; + 91D8EC216364B7084ED12776044A0640 /* ic_visibility_off@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AC0430E28848AB18A3CA8325151A98FD /* ic_visibility_off@2x.png */; }; + 91DF6BCFEF215EA66F4A564ADCC93C46 /* leveldb-library-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EC3E413A78DA754C0EC5E48FFCBE543F /* leveldb-library-dummy.m */; }; + 91F227FA1ACA21C709DA0CF20004538C /* FIRDatabaseComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = DE0A7C68BE3AE4D9CF9E2C1E46DD5AC2 /* FIRDatabaseComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 923CB835DD8318AD7EB99EDEC0B14C8C /* FIRInstallationsVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F625BC0D3779D8A1792FFCD42550E0 /* FIRInstallationsVersion.m */; }; + 92AA5B5F35F3B79348274A05E302EE2C /* FIRDataSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B8F0DF9464867C7A2D721321F226F49 /* FIRDataSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92B5409B65A42C3D778CC4F6B5AE408A /* es-AR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3BCF2E04232FF1193F3C043072D64FF8 /* es-AR.lproj */; }; + 92D6E7F5BC8F1AC4CD1FAEA20EE8BABB /* FIRAuthDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = D11EE5273DF1F4D4E3FDEE12058DFDAC /* FIRAuthDispatcher.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 92DB87D1751441DBCC224CF43AF2DEB6 /* FIRUserInfoImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C43DE3698D5BA2BF456C6F2F7532C7 /* FIRUserInfoImpl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 933A8EE8BD5698556E6641C832E924E9 /* FAtomicNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = E1D60FC645DFC56A7D6208D4B434C4F4 /* FAtomicNumber.m */; }; + 9342E20127EF18C2F8D20091861CC25E /* FBLPromise+All.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2DDAE0A59EACE0F9CF5B3655B713FB /* FBLPromise+All.h */; }; + 93493AC239D78B1790A850CC1E389B95 /* env_windows_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 27556724AA71C3E4CA6F469D53BF1EEE /* env_windows_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 93735D991E928025AE50476DCAF09CBE /* FIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 68428ACE363E5CFA4816A9F1B21640A8 /* FIndex.m */; }; + 93B48C27C6C647103C85D3D8A9DE068B /* GULReachabilityChecker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = ECA1431D8C20F0D81062BFD28CB77A98 /* GULReachabilityChecker+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 941CDBBF8A276F9D7A78A1491F0847F3 /* GTMAppAuthFetcherAuthorization+Keychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EE00313A78D550D8644DDF8C527845 /* GTMAppAuthFetcherAuthorization+Keychain.m */; }; + 94293FCBF9955603314600B5D7EDC9C6 /* FTupleOnDisconnect.h in Headers */ = {isa = PBXBuildFile; fileRef = 505214DCA8CABD3F660E0A6ACD5A60B8 /* FTupleOnDisconnect.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94401C0ABA0A5CD0A41D09ED83BDC0C4 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = A122549B6D85715608C5CBF371E00515 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94D7A47F5D3F7E23F12339B3BEDFF4B5 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = 96FD8C25F5D68FCD5169FC2E6D0B9C50 /* port.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94E29F5ABD13E2D2FE5170F070B267A4 /* FUIAccountSettingsOperationUpdateName.h in Headers */ = {isa = PBXBuildFile; fileRef = E53A609A8D12173636B10864238813E6 /* FUIAccountSettingsOperationUpdateName.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 94F45BDD28B6D698E0FABEFB8C3762DE /* FBLPromisePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 823FF738D2EDB86AD387E9C9A0628A1F /* FBLPromisePrivate.h */; }; + 951A6FBC0536F645BB5713B2D2EC7C4A /* mutexlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 68AB9C81F35DB8A4DCC516175E1F860C /* mutexlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9560DE6C92474B6264E7C5398E6E75FB /* log_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 742472618BFECC201CA07F8853313A60 /* log_writer.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 9579A8B7D3F71DEA7A59AA3729AC6D38 /* FRepoInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 207EDF36E35871F4F9C7108E522E144F /* FRepoInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9583B3E941D332DACB9506C041F853F2 /* en-IN.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 03239C2D092CAF3AABFEE00AF21A83AA /* en-IN.lproj */; }; + 959A3CDB042F5871E0E3AA527133DC81 /* FIRStorageListResult.h in Headers */ = {isa = PBXBuildFile; fileRef = EC1A5D190A1FCAB42186925B0D8D9F53 /* FIRStorageListResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 95D660DE029B3057EF7922C44E75B6FF /* OIDTokenUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 99974DDC351C326D0E6D04F23686DD5A /* OIDTokenUtilities.m */; }; + 96391DCA4E520D4A1B528F7763960069 /* FSyncPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = E34AEFBD4E8EA4B3B004C94CAA3C78C1 /* FSyncPoint.m */; }; + 96948610AAA952B1FBEB7BAC9CED8E9B /* FTrackedQueryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 104E98D4E5F9FA4F8720F910348707B0 /* FTrackedQueryManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 969CD84081A1685FA766D54A2206858D /* nn-NO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 2AFED164F46BA096C4E58DA488DF0248 /* nn-NO.lproj */; }; + 96A159C5D4849FC963A42269C75234B0 /* es-DO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 7C2013D50092AC3FF5988D10C0269AC9 /* es-DO.lproj */; }; + 96C1959138BDE575761A2EC940E121D5 /* FIRAuthSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = A71C4B5D790AC1036C87931CE820B177 /* FIRAuthSettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 971B32F3642180C9B6249CEAC634F1CE /* GULNSData+zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C403D3BDC74CA4BF92DE5C1E73CF160 /* GULNSData+zlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 973F04EA375B7A592A3ED607F8591E49 /* FIRStorageReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D66A61C6F8FE04AD5A3BADADA1656D /* FIRStorageReference.m */; }; + 978E4EDFA4BCA900839C20CC0E60CC30 /* FEventEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 368C961A58263B15D8230CEE52FB897B /* FEventEmitter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 97AE873860105489B97DD3495A3C05F6 /* FCancelEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D08AD02B34E13ED754D40A419127430 /* FCancelEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 982284C4C90F3A37CB1CEB0D81F6952A /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = A58F87C6180D374437CE7E706591B563 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 988DE22FF9CE401D0D17643FFA04FE35 /* FIRSignUpNewUserRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 187E5952DB3FBDBC83676A1C55427733 /* FIRSignUpNewUserRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 98931CDBC0DC65B5EFAC2EF6E6B8DB6A /* FIRAuthRPCResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = FF8F5D3FDDBE05A714D93F601CAFB9A6 /* FIRAuthRPCResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9920ED7AC41A3FA6E16A6BDB4FF1F1AE /* FClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 01233744AC84606574A5754E9A96964E /* FClock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9980F99E5A1481FBD4FC25BD7220095A /* FLimitedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E1827EC28E1568C4E60FC36319763CBA /* FLimitedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 99B027C8A6EA11C63C5265F29C2ACC75 /* FUIGoogleAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF88DFDB9B0042674BFDE9F60D51C7C /* FUIGoogleAuth.m */; }; + 99F6753BEB3E9CBE49919D4C42199501 /* GDTCORRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A639DDDCACAA82EDEE506C4020EF5A3 /* GDTCORRegistrar.m */; }; + 99FEA38F760C3B5F1AB54E2F68CDE95F /* FIRGetProjectConfigRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 371A2FCFDB806C4E3FDC7EDD27A1603D /* FIRGetProjectConfigRequest.m */; }; + 9A33B6A9C212905EFDE4C4AACBA0A178 /* export.h in Headers */ = {isa = PBXBuildFile; fileRef = 0540204F58B685F054530616C561282B /* export.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9A5C11FEFAF0280F937175CC9114A689 /* GTMSessionFetcher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BDF753A2E9438074A71EB24C6EE3B5A7 /* GTMSessionFetcher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9A6C9C790751416F068BD56C103E536B /* FIRVerifyPhoneNumberRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B2E3214664E3EC1748DB3C76B35B /* FIRVerifyPhoneNumberRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9B78061B40589957D4C79B090C918185 /* FIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 8652F37C3DC08512EA394530E2F59BC8 /* FIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9BBC2ECD2906A76B3376421FEC2C3C1E /* FBLPromise+Always.h in Headers */ = {isa = PBXBuildFile; fileRef = CED22AA9ED7E6EE034D56F18A5F55FC0 /* FBLPromise+Always.h */; }; + 9BEB85233C9D5F8A16D73F8ED7C06B06 /* sl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C457F92BE0D82B39FB3D3302C73322C8 /* sl.lproj */; }; + 9C14840BFDCAF32577112F75EF357082 /* FIRAuth.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A65101F6630AA9877B2525A96442662 /* FIRAuth.m */; }; + 9C30A623C38ADC322923C4195C145263 /* FIRIdentityToolkitRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B0C412BBE0A796A1761E0B94E8A1A4C2 /* FIRIdentityToolkitRequest.m */; }; + 9C33BADC9ECD2C72DCF4C1AC75C31AAF /* write_batch.h in Headers */ = {isa = PBXBuildFile; fileRef = 253FA02F3380D6F05F561C4A97AC5623 /* write_batch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C3C82D4DE315C4106CAC14F3F23D633 /* FIRFederatedAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = F8733E756435BEDCF24F263A778E0ECC /* FIRFederatedAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9C87F53FB9DCF372F43E4C582E9CD637 /* FNamedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 34EEF89628756CF6DADFCF6F7FEF044C /* FNamedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9C9E68F1D592F886CA192B393740CED5 /* FIROAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = AF4DFD6F05C1DBDF4AB4A397879384A0 /* FIROAuthProvider.m */; }; + 9CBD80B9EC20D09184982C3B1490A6F9 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = A2FB23E8BFBE90DE7FC2150F1FB132A1 /* FIRComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D1AA39AFCDE0D6AD55B0846FA7E59A7 /* FCompleteChildSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D00558C0328CCDB118481BC1BB4058F2 /* FCompleteChildSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D5E0F06B552C012EBAB3E6C8E4705DC /* FNextPushId.h in Headers */ = {isa = PBXBuildFile; fileRef = 570063252316BB9DC95F50B0BEC2AE1C /* FNextPushId.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9DD8C66385374FED4BBEB88CFEE1AA88 /* bg.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 55A5039F460D923DB08EEE1CBDE8081D /* bg.lproj */; }; + 9DF45ED125C847BE7A7BBE63A9C5E0B2 /* FIRCoreDiagnosticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FBDA9871C1CC5320359E77952F468C2 /* FIRCoreDiagnosticsData.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9E05210EB198E73CB1A7DADF2D219034 /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FC01874018CA0C937F043AF841B3189 /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9E16F41FE897503F47580345EDFA431F /* FImmutableTree.h in Headers */ = {isa = PBXBuildFile; fileRef = C877AEB4DB96DADD3B3B880F11E807FB /* FImmutableTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9E4622FC3425305AEEF9CD631E9D7704 /* c.h in Headers */ = {isa = PBXBuildFile; fileRef = A54237B6213E123B38287547B3062207 /* c.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9E8D4102065D27D387D10943D3B95479 /* FIREmailAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 775B864B453C9AE0D8B96507F09A9F80 /* FIREmailAuthProvider.m */; }; + 9EAE5B3A6CB274A9C857DB49FC5D0C4E /* FBLPromise+Validate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EA4E84EC07EDEE7CEB2CF5CB07768D0 /* FBLPromise+Validate.h */; }; + 9F0740CAA50D4D3EC7AC59B9DAD6CDD6 /* FIRPhoneMultiFactorAssertion.h in Headers */ = {isa = PBXBuildFile; fileRef = B53E593E59C566978EEABD9BBAE4E82C /* FIRPhoneMultiFactorAssertion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F431113F61815502B9F771D243A9907 /* FConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D67FC5FEB279446C5CFB3287D38A9DD /* FConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9F5F67A891539CECE9C1A3285F62719A /* GDTCORTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 48FAFEB26DDA963B5ADB9B5659C279A4 /* GDTCORTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F71C538973429360D8A83A31336266D /* FIRInstallationsVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B2E268A97351C2CC543523DFDCB9F94 /* FIRInstallationsVersion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F9A6E681D075EC39272BAE1870FA707 /* FQueryParams.h in Headers */ = {isa = PBXBuildFile; fileRef = AAF8E5F6347530C455055D47E32788FE /* FQueryParams.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9FC70D20B3369EE9CBB59C2955C7D232 /* GULKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6259D501189F90B7AE0391DF9109BD35 /* GULKeychainUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9FE39550C663547E3DCC144015F56F9C /* FIRAuthWebViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6664F046DE36C873274CEE8DFF2BECFD /* FIRAuthWebViewController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9FE95AB76727B51B2D8C05A47933AB11 /* ic_visibility@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D591A8AD1DC179AB95D8C88D42E28597 /* ic_visibility@3x.png */; }; + 9FEBAC4CB9A3FCD902C6008EBF993E52 /* filter_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = F01F346D4AD11A343B839A4C4244BB53 /* filter_policy.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + A04AA3C1341FDC92BA388EF29890120D /* FIRFacebookAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 369A1A5944F95579358CD6744CA18E2F /* FIRFacebookAuthCredential.m */; }; + A0A52BBB2973E7E6BF1D4E821BAB916F /* GDTCCTCompressionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 858E389F4C5941E87CE495D9F4C3F1D5 /* GDTCCTCompressionHelper.m */; }; + A0BF51881987376BC9B74063328B9AC5 /* FIRInstallationsStoredItem.h in Headers */ = {isa = PBXBuildFile; fileRef = C85496CC24BDC7756948ADF2E7D60E04 /* FIRInstallationsStoredItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A0D1F0D02C2DB0BEB765658CDF51399F /* db_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D26B5B77EF3AE1B591E57CD37A8A72 /* db_impl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A129DBC6CF1F6675405940C7D5BECBAF /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = D85A7B28B871DD677E7668E92BB6D96A /* FIRDependency.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A14710681730656A8EE4F2793773C18B /* OIDAuthorizationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 762FA9EE5DB6C426EB4469042AC1AF92 /* OIDAuthorizationResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A14D2F8BB22E729406AB0BB92447544C /* FListenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 917C3FA5633CF0BC4302E35ED0133084 /* FListenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A1899D60120878FAAC7E9A0E1B3E38E7 /* FIRUserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 82C7731D87C6760CDF18BCA19341307A /* FIRUserInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A18B199CC3D0AC60857A9546D6BC552D /* FBLPromise+Wrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DC7679A2F6487DA883CD86CD58DD9FE /* FBLPromise+Wrap.m */; }; + A1AF5BF63FEEA98CB2D165039170E6F7 /* OIDAuthorizationService+IOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 6080376A14E37CCAB6B3B0C2BA0D0855 /* OIDAuthorizationService+IOS.m */; }; + A1D8C9FAE7C7896ED69973B0957A2A68 /* FUIAccountSettingsOperationForgotPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B54C1685D4AACE5220DAA13C8DAF23A /* FUIAccountSettingsOperationForgotPassword.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A1FD06AEB073D6E84F7629C7C2BC2833 /* pt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 39D2B86BB6BAD94CA0B74548C99551B5 /* pt.lproj */; }; + A23EA146EFC5EC2BDADEBF20192A9D10 /* FIRMultiFactor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EE688B7F2552F591256057AE7161815 /* FIRMultiFactor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A24DB31365AC62EF3D68A5CCBE4EDD81 /* FTrackedQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 9237CE067B92CC661714D1430998DA2D /* FTrackedQuery.m */; }; + A2D32D0DF7204674CF2AFB8BEE709C6D /* FIRMutableData_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = EE82A376F70C60AA9E73076A0E27ABB2 /* FIRMutableData_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A2EB72DBAEA526F00FEC5D50D85CA41B /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = E8F4C1D122F022ACE1D89ABFFF55CA0E /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A31F4044B8F9972C992C68F81DD19605 /* es-SV.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 73C7F092D26BAFEA89D9BDF33EA12285 /* es-SV.lproj */; }; + A3447593D7E7311E4E94634D138344B0 /* FIRDatabaseConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 31F1C186A4EAC68717CA9A6D6AE22852 /* FIRDatabaseConfig.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A3DD8CF7B61C9BB1CD67B29F521D7195 /* FIRNoopAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 144230DCCAA8A18DA6384E2CBB093FFC /* FIRNoopAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A3F18BECA57B9B33FD0735EE363AB67F /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = E799655A87365710A1EB972B120BAE90 /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A453998DE677225FC20FE5E601C7D596 /* FIRSendVerificationCodeResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = FC0ADC33764603966493C028E141A96C /* FIRSendVerificationCodeResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A4C659C8D886BDB8389D46EC59134C7B /* FLevelDBStorageEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 213BBD3DBEF0184BBDFCEB20FF14F4EE /* FLevelDBStorageEngine.m */; }; + A4D53EE647F5DF3411B009F6598CC4AC /* FIRAuthNotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D2416E1A611AAAA6CE13CE9FB3A88784 /* FIRAuthNotificationManager.m */; }; + A4DF4AC097E6C5DD3364EE8B68093E20 /* GoogleUtilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D678FD741DD09088553BA3DC1E003846 /* GoogleUtilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A4FF7952658AA4749E1203852EAF3EF5 /* iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 6403E384584CBFB8805D55588F538224 /* iterator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A5041067609D4D22085164D4C09F6C5D /* GDTCCTUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = ADCE0BC750EA080093025FC468D756B3 /* GDTCCTUploader.m */; }; + A57DB5709355A7460C93C161EF8B8971 /* ar.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 444161411F02B826835C81A17C1E4285 /* ar.lproj */; }; + A58760AD72BC23A29A025E8873D4686E /* GDTCORStorageProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 06AE775865E552A747572F5608D9863A /* GDTCORStorageProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A5CB9523A7B77E14A991E8C839F008EB /* FIRPhoneMultiFactorAssertion.m in Sources */ = {isa = PBXBuildFile; fileRef = CD1796471948B825202E4B28A5B2A6B9 /* FIRPhoneMultiFactorAssertion.m */; }; + A6241D9B2D4E672378D5F036D1B977B1 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 20070732AC1D13563706D375942B5198 /* FIRComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A6AF52EDF168718FB5AC4607D589F3B1 /* FIRStorageListTask.h in Headers */ = {isa = PBXBuildFile; fileRef = D18899BE4BC7E2D4F952DB97896F1A68 /* FIRStorageListTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A6D861F8BA510EE9B3D14423A664DDE2 /* FIRInstallationsStoredItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FA4D3EEB0242AE4F3CCF1D1B12BB2D5 /* FIRInstallationsStoredItem.m */; }; + A71642B53A475EE9AE493557F253A095 /* ja.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 76E51504F5FFB6652AFD71EF86591B2A /* ja.lproj */; }; + A722B9358F15537F8597BCB54C04D08E /* FRepoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 85F1F6036F7E1CBEF9C35C3689DE4CAE /* FRepoManager.m */; }; + A784F41C2D045F1AB7E9F394FBB00688 /* GULKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E24B05160E278D466B32F147A97FE68 /* GULKeychainUtils.m */; }; + A78549116DDF889C58A9F46898B2B71F /* FIRInstallationsSingleOperationPromiseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5219D7E4DCD40901B20474422BEB8E0D /* FIRInstallationsSingleOperationPromiseCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A79384496D746E00B4F32F04CB1AD13A /* FIRGoogleAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92ABD50E475C05DDFA7B0A5531B74A /* FIRGoogleAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A79949097A6A6DB0E2E94B5ED30E40BA /* ta.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 04D93189E444EF105CE4F9D654BE2315 /* ta.lproj */; }; + A7B75B6766CBB8772AFB0734E4012264 /* FPriorityIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = B0382A72B82D98EB0659D080E198382F /* FPriorityIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A7B9EBEEC714CFA6B00B694ADB2F1CB8 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 82FB7E4D042D8701D3495BC636CF8FAC /* FIRComponentType.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A807351D7EDBD43936003A83C5E625BE /* cct.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CBFB69FAF7FD49AC3054E91F5ED2A /* cct.nanopb.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A80F4FE31E9C5E7397DD7E457639C91F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + A8278716ED8C8E8703B2F8AB2613CFED /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A4A40F06A6A8E619437AE6C82A30FB8 /* FIRDependency.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A82B62CE863483B4FB7661341B35378D /* GDTCORRegistrar_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 26CCE65941065E0C84C417825219AFB5 /* GDTCORRegistrar_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A8316A4B275335565F9E8CB7552874BF /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A48AB5E3FB50C36BA0EC0B20B809C21 /* FIRDependency.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A837179BAD5CC1FFC6BFAC2C5C67E334 /* OIDServiceConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F6C0E7581284480F32192794A5A25698 /* OIDServiceConfiguration.m */; }; + A83D12FC092D2F7C2319ABDC8DB44081 /* FMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AFC363CB444A494A51C8E1CF891B276 /* FMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A86AE2F5654920CE67861263686F1B62 /* FIRGameCenterAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = FD8A4AC55991A3986691EF3AC1B9D012 /* FIRGameCenterAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A89E5739575FA08DEA9CBB22657E9B01 /* firebasecore.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = B9C76868E9938C4102BD1215FD5A8374 /* firebasecore.nanopb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A8AD2F68486AC0F2F1F8358BED647B24 /* GULOriginalIMPConvenienceMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 580FEBB5E7903DF0A726E950419BFB5D /* GULOriginalIMPConvenienceMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A8CDA185643967D2FB7FEC96DCA7954B /* vi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 002837788CEDF728C9F8B00AE09AF35E /* vi.lproj */; }; + A8F02CFE73D72F2F2527B214D5506118 /* FImmutableTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 49A415C83A5EB9C040FDD6EEC57B55E2 /* FImmutableTree.m */; }; + A946BA4157746AA69CC1DAF1232397D5 /* FIRApp.h in Headers */ = {isa = PBXBuildFile; fileRef = 18A7C0C0F3FDF3AEAF2C3758A25AFD61 /* FIRApp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A964875BA642838FD01FDFF53E5C6E20 /* fr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 16296FC7FAD4F7911C51F68AFD78E15F /* fr.lproj */; }; + A9703CE2B57854BC58213AE3766D6AAB /* FWriteTreeRef.m in Sources */ = {isa = PBXBuildFile; fileRef = AF143C3AEAFA1634232E7FDB22A4A7F2 /* FWriteTreeRef.m */; }; + A97592B677E28AEB0899B5F7FBFBCB96 /* FIRStorageTokenAuthorizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 67A202C7FB39D4EF6220EB50BAA61AFE /* FIRStorageTokenAuthorizer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A9E1D9E34515B7D31A8CC0F95B6B29CD /* two_level_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 48B6C0DC5B6FA45680468DD2690747C7 /* two_level_iterator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A9FF7C8B78F63CAD990E872F352B5F08 /* es-CO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 1CD458A32FF2A6B04A8196DCD333D719 /* es-CO.lproj */; }; + AA107EC1612EC9490D8C8331BEB3679D /* GDTCORReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = DF253DFDBF8A328A69C50E35AA66F7A9 /* GDTCORReachability.m */; }; + AA10A572E5964B3B12BE4D381B7A62D7 /* FirebaseStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 09A097B832C0A5236DD3C244CE58A25C /* FirebaseStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA17C6D52EBC4DD945C43E225CF32581 /* GTMAppAuthFetcherAuthorization+Keychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 6350872202105F88AB9E4C49B955A981 /* GTMAppAuthFetcherAuthorization+Keychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA1838ACEF3E00C8B3216AFFBE86FBA4 /* FIRStorageTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D2DEB829F75D19F6A96A02CE8E216FA1 /* FIRStorageTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AA252720B5973042041CA01C9F37EDDE /* FIRStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EA0C271CB77739BABDAAFE7F7636239 /* FIRStorage.m */; }; + AA3BE332B851918B23E03F283868116C /* OIDError.h in Headers */ = {isa = PBXBuildFile; fileRef = 155468BB75CD9DCF1B69D9F7A0A9355D /* OIDError.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AAB1C6C099525ACA3B9AD0ADDF075EEE /* FIRTransactionResult_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 21BF9FC4620C4B9524CE633385AE1764 /* FIRTransactionResult_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AAB20654E0156F30AAAFEDC0E8E54644 /* table_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = D9C51A32FED68D67E048C2F602C45FE5 /* table_cache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AB04A8A3DFE879B7205875E30A8ED6EF /* FIRInstallationsSingleOperationPromiseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 69F8D7A867F609C67B74BB85FF357F12 /* FIRInstallationsSingleOperationPromiseCache.m */; }; + ABD05441BDFB77157B8020E38F6ED265 /* FIRGetOOBConfirmationCodeRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 15EDF646C56C65236F9F00B1FAF8A64D /* FIRGetOOBConfirmationCodeRequest.m */; }; + ABEB1A56D2C80F898303252D8CDFDBF7 /* FStringUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 2952573EE05F206F04E91F8CE6DBE770 /* FStringUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ABFE52B4F220ABF754D967773D98F74F /* FViewCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DF33474F2924572E91E1E1B155DB0BE4 /* FViewCache.m */; }; + AC1E95A9323BE0473FA9CDBEF06FDC98 /* FStringUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF46F360C12AAC644A4E6A1F433F683 /* FStringUtilities.m */; }; + AC35785AD6ECF42C7DA342AD6613DD0E /* FSparseSnapshotTree.h in Headers */ = {isa = PBXBuildFile; fileRef = FA971777AE9035EA63091527E76D1AF1 /* FSparseSnapshotTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AC4F78E7BB3D3F069A0D5DC47B347BA0 /* FIRCoreDiagnostics.m in Sources */ = {isa = PBXBuildFile; fileRef = 98E076D44BAA2867EABD71555B9ADF26 /* FIRCoreDiagnostics.m */; }; + AC6AAF26EFA3971640B8FDB782ADD3CA /* bloom.cc in Sources */ = {isa = PBXBuildFile; fileRef = C38527266A6D5DDFB333ABB2566D6783 /* bloom.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + AC95C3D0C8204091188F4276314ED68D /* es-NI.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 58468784E905EC12C0878CEA8C1CA891 /* es-NI.lproj */; }; + ACD46433145A93206FCDDB6C4CDFA865 /* FSRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 41C974DAB5B079CE71E75DB13DFC0CC7 /* FSRWebSocket.m */; }; + AD1D66E7CC1877C0ECD63BC5F1CBAF3D /* FTreeNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B69E273AC1F848FB9E6B3E2592B78DF /* FTreeNode.m */; }; + ADB322EAF3B8C2E6D2655B03D1A20120 /* FBLPromise+Reduce.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = DE3965AFA52554A33633B6C0264AAFB7 /* FBLPromise+Reduce.h */; }; + ADCEC74787D20ED5DC976BB361C21177 /* FIndexedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FE785EE6344006DCC6CCF1EB97E4675 /* FIndexedFilter.m */; }; + ADCF1FB700F702053293F3BA943084AF /* es-US.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BBC868C8D7509594738EB3FF2E0097AF /* es-US.lproj */; }; + ADD0E36A420FAACCEAC7905AA5E0317D /* pl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0534AAF51A65ACC6357CCDC6F5B9A17A /* pl.lproj */; }; + ADD68D5DE76122186E4F6C8BFD098933 /* ur.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 8EAB0E19E6BFAE72A24B17CDAE58272E /* ur.lproj */; }; + AE07D07F98D805B39CAAB4E89F1E87B8 /* OIDServiceConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = D0347ABD7E493B8A79752245481CB399 /* OIDServiceConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AE0D2748DD86501DFA486CE10616CDF8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E942549C86F57C477E3AC759C80C513 /* Security.framework */; }; + AE1B61B2CBC39BFFA0F17E60CC012A25 /* FIRSetAccountInfoRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 477A700BD923CF5A1643043ADC94EC97 /* FIRSetAccountInfoRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE289590D289D602BD6BBB20321B6BE3 /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = F26FF619FBA8F5E01A361CF0C1860F6B /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE2A4AAA9A98DE08FB34CEBD86E73513 /* FirebaseCoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A4C16C9132307023FAF3F4A82725766A /* FirebaseCoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE892DF714C5A2F1BDB6BDE8CE8599A9 /* fbase64.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B11264065182D6FAD716FE09C948EE /* fbase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AEA108EA49B457476CB6335C08193B15 /* FRepo.m in Sources */ = {isa = PBXBuildFile; fileRef = AF966A01B41EB868CD964B1A909147EB /* FRepo.m */; }; + AED5EB92C1BBDB0227A8C83E6F839542 /* ur.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 163D0E58B78F8F26B3921C24D10FE991 /* ur.lproj */; }; + AF0F2DD74E6CF1F7060C0F09D128B58E /* FIRStorageListTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CE5CAD485E3BB64ADEA5F812EAD1AFF /* FIRStorageListTask.m */; }; + AF4CA8342FD28D7F603651275559EECD /* en-GB.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 5A869C047DA714685FC173B0BEBCEC95 /* en-GB.lproj */; }; + AF756AB48E3B3095C78B0AF82BD84FD6 /* FBLPromise+Do.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4E5F43CF7B994C577E41DD7E44C33231 /* FBLPromise+Do.h */; }; + B00AF14E70C26C9D19EDB3AB4F04123E /* OIDRegistrationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CEADACE08A5687E217E73FEB4D216E2D /* OIDRegistrationRequest.m */; }; + B02215846A755E1CC7CEE04F580CC05D /* nb.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A791424A89A3CDA5752E45E7C544B668 /* nb.lproj */; }; + B02CF31C4FCAF3751BD1ED6C52B06056 /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 327D01056854E2B13B40561F172984A5 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B033C7DABB452098F148FA326A12467B /* format.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC664C1A73AF5E0E4D8D49709109472E /* format.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B03AD60FE916920455F438761A2EA7F4 /* FirebaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = D15C1FD503313790B31F95082523E068 /* FirebaseCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B089A1D99D75DFD5AD881E31885F7897 /* filter_policy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B7D65B60CA4A510AF8323E801381667 /* filter_policy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B0CCE74526E2B1199108FC568234C9C5 /* FBLPromise+Await.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 65B219104CD42208B88312DE148CB3A0 /* FBLPromise+Await.h */; }; + B14E9647B3D61648228B91DD6F1A2CB5 /* FIRStoragePath.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF5CCBA93E845A4675A58E020BC2BC8 /* FIRStoragePath.m */; }; + B1B9D7366A9E4175DC4A545555B169AC /* FImmutableSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = AF4370CCD5C550D5805C9E19ADDBB5B3 /* FImmutableSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B1C98340BEF4FDDFB975C6A3AA83A106 /* FIRConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 38DB566120E8E842EE7213F780372006 /* FIRConfiguration.m */; }; + B1D5CBA235E912985957637B062E5003 /* FIRAuthStoredUserManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3AD31088110FDA73241B3581A2B2D7 /* FIRAuthStoredUserManager.m */; }; + B1E49935E84945F6EE24B225CFC278BC /* FIRInstallationsAuthTokenResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C26D6616E92CB6CEF0C796513A00E7D /* FIRInstallationsAuthTokenResultInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B1FA064E66162EA9C8B99589AB800A7F /* zh-Hant-TW.lproj in Resources */ = {isa = PBXBuildFile; fileRef = E68A7082C16971B6E34E2B534C5CA9CF /* zh-Hant-TW.lproj */; }; + B2019EE7CE5C1760DB056D6833E0A6C4 /* FTupleFirebase.m in Sources */ = {isa = PBXBuildFile; fileRef = F1D52AFE6BB5A995128447A1AF90B5D1 /* FTupleFirebase.m */; }; + B24CD4EC9A25599C0921961C39208C3A /* FIRMultiFactorResolver+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 40D807BDAEF7E00EC311084CEB3E716B /* FIRMultiFactorResolver+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B25F6CE0F40D81A392EC5E7E28538F20 /* FUIAccountSettingsOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = C4E8A02EA89196599EEA4611A384C74A /* FUIAccountSettingsOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B272A67E54DA88EE6D1B25B511380E85 /* zh-Hans.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9C11205E4D4588C7ABA50978488F6849 /* zh-Hans.lproj */; }; + B277F79F14E95256EC75448495435FAE /* FIRGitHubAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF9DED7488ECE428D645CC657AD96A7 /* FIRGitHubAuthProvider.m */; }; + B29E685FA0F79B34DEEBD992F6CBCEEC /* FIRAuthURLPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D89B61F748E61F84C2D14454827CD41 /* FIRAuthURLPresenter.m */; }; + B2A2330F9264C322394B3EE8A9DFCB28 /* nl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 01319D0532FDE21A1DAB1F8E6E5716CE /* nl.lproj */; }; + B2DB7D77CDAF01320311D54A6C2B6A18 /* zh-Hant.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 65FC5F7A295C348696803A456B61FBBF /* zh-Hant.lproj */; }; + B32A3AFA04977EF646295A55AE05BB42 /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF78B774DA999F5D69F23DCEDDC29DF /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B3722C8826B36658252E4C72BC9889C6 /* FLLRBEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 95171A26BA94A2DC6A9774AFE265085B /* FLLRBEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B37568066FD3EA9B0A9C4749C4FFD55E /* FEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = D320ABBA071441793237FDCC5BF2906A /* FEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B37E968F9A7B713E9D6DA6C95AF8F073 /* es-VE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 23D196E2657D5CF6B7EEEA795134088B /* es-VE.lproj */; }; + B3B077E290BC952DA42B5640CA5DE204 /* FIRAuthUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FB877E48D135890070C81A252F9515C /* FIRAuthUserDefaults.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B409B8076034296CA2FA6F4B31E636CC /* GoogleDataTransport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A24AAC884CBBE3470180211F88008142 /* GoogleDataTransport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B441611B7F0A39099F3A46949B0A93B9 /* ln.lproj in Resources */ = {isa = PBXBuildFile; fileRef = CD681182A0A791D44FA0677AAFE46C33 /* ln.lproj */; }; + B44DDF94C083D4E6762268A54E9E7925 /* FIRPhoneMultiFactorGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3F00A4E6D8568D60392BAC86AE8673 /* FIRPhoneMultiFactorGenerator.m */; }; + B48B4C92B1B992AB67D650AD120B59F0 /* FPersistentConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CA5B41F52E3B66856135E15CC4759A8 /* FPersistentConnection.m */; }; + B52BB6202539D138732BC2F2521A00BC /* es-PE.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3AB38AF65C51703D0C443B947C88594F /* es-PE.lproj */; }; + B531FEE2F1C9E74B73647EC98DD0ECE6 /* es-UY.lproj in Resources */ = {isa = PBXBuildFile; fileRef = DCF3B50D1BFBD7F6BA12307093BA9BD2 /* es-UY.lproj */; }; + B54C74810389280E1F77C0DBCB1FD458 /* builder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2898C5A20C3702B07918D03F9FBB0C3C /* builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B5521C308994B7829E6626188508F0E0 /* FIRNoopAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 463D1EAEEBD47D9938BCF8A662DC6A86 /* FIRNoopAuthTokenProvider.m */; }; + B5669EE2BFAA822E4C2EF780AA370418 /* FIRAuthRequestConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 695E99910948F9E8E6793FC52BD6AA01 /* FIRAuthRequestConfiguration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B56B41D5962C27D301A1E174A31C222E /* GULHeartbeatDateStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = B7FE9445781AA6E6E3D1ECB979847E15 /* GULHeartbeatDateStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B5AD23C44AB0C2D067FB433629BA13DA /* ln.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 8BE1FBFA703800A2B83E044EE565A1A6 /* ln.lproj */; }; + B5B104C87A80CCB6172B25D329AF6573 /* FIRMultiFactorAssertion.m in Sources */ = {isa = PBXBuildFile; fileRef = 67159BAA40CC337613A80836DD8BF37D /* FIRMultiFactorAssertion.m */; }; + B5C5172BB02980A57FED91C71AD08006 /* FIRAuthInterop.h in Headers */ = {isa = PBXBuildFile; fileRef = E23E05F6789EEAA15EACA16603FBC88A /* FIRAuthInterop.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B6328917F97205BD6DAAD02FC5D26E2B /* pt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0676931B0B675CD8006C8315CEDA9D2D /* pt.lproj */; }; + B65C2A1A1C756F2CC67B7468FE537E75 /* FCachePolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = CFDAECD713E8EE3C5428D7BCBF22111C /* FCachePolicy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B6620134F7F9D18E523F1E7634934462 /* write_batch_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = F8267B5FBB4E05B085FAA667C3AE0B4E /* write_batch_internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B6A43991EB70AD84E570E24F97A05C06 /* FirebaseUI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B224DAD75F17390167B044A8AC13A27A /* FirebaseUI-dummy.m */; }; + B6ECFD8B80DB8001DDEE0DB009FC3A7C /* FIRStorageUploadTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1564C41BABD3DE7AA9CA05FEC60DFFD6 /* FIRStorageUploadTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B6F865BC534B106F368EA31F8923CEEB /* ic_google@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D32F42267B26545CE5E602067ACDC089 /* ic_google@3x.png */; }; + B7189C2F2C54A54B3AB5C3F216466FD8 /* ic_google.png in Resources */ = {isa = PBXBuildFile; fileRef = F14BBD6EFFD126F1D545DD56A2CC772E /* ic_google.png */; }; + B727B4805AB5FEE5B5DF4546FB713DF1 /* GULReachabilityChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AD08C35B5ACC18737C7E17D782539A9 /* GULReachabilityChecker.m */; }; + B76123BD5E999929EEBED5F55EE66D85 /* FIROAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CC6A8024E61AF153A776058F0093984 /* FIROAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B7B63DC78FF94B33A1D34568261823C1 /* es-US.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0BE0652F32B8FA6E5D02FA260895209B /* es-US.lproj */; }; + B7FBAA203ECBB4D9AC70C22EE1EE9623 /* FirebaseUI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0390D03D2B6A00354D273E01C6ABA200 /* FirebaseUI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8131349639510A9567770D9A89168A0 /* en.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 66390B4F65D06861288DF3E89EB760F4 /* en.lproj */; }; + B81AEE4361D3E800FFD1AC49B81BDD83 /* GDTCORUploadPackage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6617BF2CDA7A9B322A0459463CD349C3 /* GDTCORUploadPackage_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B822D80139D33614A8D119F71C9801F5 /* FirebaseDatabase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C38D7625DDE875B5097AAC4D90B1F41D /* FirebaseDatabase-dummy.m */; }; + B82BB2163ACC8827A4936155C85F9FF9 /* FIRTransactionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = CAD238E59070BFF625623ECA05A24EBE /* FIRTransactionResult.m */; }; + B8C440235C0D9EF950260FF4E2DFFF55 /* fi.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3196AD45943E4CD873BAA17255DC4131 /* fi.lproj */; }; + B8C4453F4A7ABF993101ED40BE8812D9 /* GDTCORAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A26EC884A9999B199DC3FAA4137C4AB /* GDTCORAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B947E3208B2FFE506E5BF0C2DC866D08 /* GDTCCTPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D5FBD9CA1599240429F1765EBF7ED323 /* GDTCCTPrioritizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B94E09C1E2549162E5D7068F3F4767FA /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = DD6E7DB7F56371C9D91F90EC3F06B43D /* FIRErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B9DFB07597C2F67EBE4AFFEA69DE617F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + BA54A3709D477EFE277F2DB73772979E /* GULLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 11C637F7FD1011CD32D6B2CF1B22A474 /* GULLogger.m */; }; + BA599917E4E9C131A2AFFCF7D8AEFADD /* FIRAuthProtoStartMFAPhoneRequestInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = A0ACEEDB9C66A05F00FB2DC2683FD087 /* FIRAuthProtoStartMFAPhoneRequestInfo.m */; }; + BA6E31A35A91951C7F2CDAB31D5E228F /* FIRGetOOBConfirmationCodeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = B7698798113828A6F12BD9B8EC907A4B /* FIRGetOOBConfirmationCodeRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BA6E768137D38737A16803625253B55B /* GDTCORTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B54EDA0B44A3B61BA9E8304A43868A /* GDTCORTransformer.m */; }; + BA7AE5FD43B1E8BA87B93E0EAB39E391 /* GoogleDataTransportCCTSupport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5674BB3E7376B13F3BFA81723D39ABC5 /* GoogleDataTransportCCTSupport-dummy.m */; }; + BB0BEA6B1B8BBBDA8ABE5FDF85171637 /* GULNetworkURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 31F0F6B3F5A086DD87C96BDCFA6D3070 /* GULNetworkURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BB203C87441D3129D2BC46D71F8B36AE /* FQuerySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 93350B3059FFA3016BE438DE54C68169 /* FQuerySpec.m */; }; + BB52C704A0547D78D4B5024FD5C2B26E /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A62BB8032FBA738F4F2D57C13670651 /* cache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BB6B02BE21083F91EE3B0785E60A1C90 /* FIRConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CEA234D8D45743863BF4E8BDB6ECA14 /* FIRConfigurationInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BBC602EC86EB71FC4ACD5728C9058E23 /* OIDRegistrationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 16AF194D65A9EDA527517C4CBA700597 /* OIDRegistrationRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BBCEEEC509BF6A9787EED2A08B678B47 /* FBLPromises.h in Headers */ = {isa = PBXBuildFile; fileRef = 4900DB7C20F8911744B754D0004709A8 /* FBLPromises.h */; }; + BC28630AEA12517D2B40A45134C42E78 /* FTransformedEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = EB9053EF1ABC9AAFACEFBF5649C58920 /* FTransformedEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC3C7D1A1FA9DA69185BDF00CDA4C4EE /* FIndexedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 505DC4F2361DB07F86AC3E424C21849A /* FIndexedNode.m */; }; + BC4CBD3E4A3760B4E2679B261709BCE2 /* cs.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 45D396EDB48B3E1CED1969E1ABD6A9A1 /* cs.lproj */; }; + BC6076CC2D9A8B33AF0B4558B31FC616 /* FIRAuthErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F0A65267EACC1715344BFD364530CF2 /* FIRAuthErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BC76DCB86613935CF0F4D01BD1C95C54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + BD52784A213B66A87F98A9AFC2E9F181 /* FPriorityIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = A7AFBD062FA62F077ECC87E01A4138FC /* FPriorityIndex.m */; }; + BE96166A6FBFAA2DC07A5D8AD147BFD5 /* FSyncTree.m in Sources */ = {isa = PBXBuildFile; fileRef = C6B3A10FE7BA9E0E113004E04AB0D9FA /* FSyncTree.m */; }; + BECC3E12395C5B73E231B9F4484DCA22 /* FIRDatabaseReference.h in Headers */ = {isa = PBXBuildFile; fileRef = AB8D15C266FE082A037570E11AE0AE14 /* FIRDatabaseReference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BF18BDF2A230234AC681FC729A197F05 /* Pods-MyExperiences-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 50869C4A83B8711B77611300BCA59CB6 /* Pods-MyExperiences-dummy.m */; }; + BF359B9968091F3A829575C466660D4B /* GTMSessionFetcherService.m in Sources */ = {isa = PBXBuildFile; fileRef = FC2A2B517E03A8347DD866AB5D8629EC /* GTMSessionFetcherService.m */; }; + BF507994176A3C34EE789BB992B433F6 /* FPruneForest.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FEC1F12EB515DFCF19288525A7FBAE6 /* FPruneForest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BF980319D34B50891CE50867B3EBF076 /* lt.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 80E00FBA13DD98479E065206F43AB591 /* lt.lproj */; }; + C009BF9383B259CD9DEC0B039926C38B /* FIRBundleUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 79DC4E4C9D18B8167EC254230731F98F /* FIRBundleUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C02A8677E90C8C963C54989F1D6C8F90 /* FIRStorageComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FAB3E24D105A6595C0A0EFA8B1674F /* FIRStorageComponent.m */; }; + C052D4F57373AC725E724B316925EEA6 /* FIRSecureTokenService.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0D0E3CC089D8D56B6F1EA76C078E22 /* FIRSecureTokenService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C0592DE29AD7F829C8356160EF6E753C /* FLLRBNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C73C0921C9BCBB67271CD840F1E8552 /* FLLRBNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C0988DCAEF52C0A605F758B0688C00E5 /* es-PA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 16222C91E613CBB3BA3B1594E89FD7D7 /* es-PA.lproj */; }; + C099234E569B89298481103E98A64056 /* es-GT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = E04D809D94C88A8E91E01FA4F33D3DD4 /* es-GT.lproj */; }; + C108416C60A490E5C1E8AAF7D42CB5B7 /* FChange.h in Headers */ = {isa = PBXBuildFile; fileRef = D191AC962BC4DF1A4C9B41B31D176C69 /* FChange.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C144B9AC5D51D455FD59811C66C615B1 /* FTransformedEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 8810AE5E10E7D7E8DB0D9B3CB32C0D9B /* FTransformedEnumerator.m */; }; + C1C8F682F63742C103D424D8CF91990A /* FIRAuthWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 25BF8489D43A221CCEECB7FB5BAB2A7B /* FIRAuthWebView.m */; }; + C1D269ECFD03FC535DFDF9DCA10B8172 /* FServerValues.m in Sources */ = {isa = PBXBuildFile; fileRef = D977A66079935F32A4225D1C90E2615B /* FServerValues.m */; }; + C1DB956F940BD70C4E798C17C81317AA /* FTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 69CE82213B430ED4CC3D6630855D6FBD /* FTreeNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C1E73052E8A551C53DCAE302B77A4A46 /* FBLPromise+Retry.m in Sources */ = {isa = PBXBuildFile; fileRef = E0621BC05ED00710FFB1A6F7DA1AE42A /* FBLPromise+Retry.m */; }; + C1FE53C9812D63B00503FCFE5A73073A /* FIRInstallationsIIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A854E381D55BE2A7E3E8AABADB04EBE /* FIRInstallationsIIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C23F697B76C8D3242F232D958E0C00E3 /* OIDAuthorizationService.m in Sources */ = {isa = PBXBuildFile; fileRef = BDE67C480BC4E7C0C8D3379267B21193 /* OIDAuthorizationService.m */; }; + C2AD48867D557C2872A51ADD54507FC1 /* FIRStartMFAEnrollmentResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 25585B514F999F152B161BDD883EF1FC /* FIRStartMFAEnrollmentResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C2FBDF0C76469142C9795BD98B0DCBF9 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 29D5A4375D1E8A2A55723BFF02AA7005 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C2FF1623A2AD96DD41AD38723AF3BBA6 /* FIRCreateAuthURIResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = DC72213D4B3FE7DE0AE14E86B63763C3 /* FIRCreateAuthURIResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C359863B7FF01F6B19CDA89D30126EE6 /* OIDAuthorizationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BA57690C4CA9DFE949ED25284DEB517 /* OIDAuthorizationRequest.m */; }; + C39D7CE684DCF8EBB3706DD17FCA1355 /* FTupleObjectNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 10C804434EE90A3648EAC6407DCF9D28 /* FTupleObjectNode.m */; }; + C3A8463329338FF52B993E398488F184 /* sk.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 45C09F6B2C40752E3427CB95ECEC8ACC /* sk.lproj */; }; + C3DC1814C54F9047BC3F622CE76EE493 /* FirebaseDatabase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A17A81DAC159F24CE9466BA8B0DE04D /* FirebaseDatabase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C449982CC108228D7A3AFE1428666DB5 /* fbase64.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A44D696F2163787D7CA8EF6B66B3B29 /* fbase64.c */; }; + C462913B0E7361B8D2BC26260D92CD0F /* FIRAuthDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = DE23FFEDE913A0F515A9DD8F1CF6D5DE /* FIRAuthDispatcher.m */; }; + C4A5292FFAEDC02154ACB30201BFCDBD /* FAtomicNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = B0C9BF1BD3D64D58780FCF7D993843EA /* FAtomicNumber.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C4E0987FD50FEE7737967B8D83201220 /* es-PR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 8AA74947BFD3B18B07530AB29E37CB2B /* es-PR.lproj */; }; + C4F860796ED8DFD85800BACDE3A1B8C6 /* FIRSendVerificationCodeRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = C2A84F61584DBCC3BD946DCDB89CB968 /* FIRSendVerificationCodeRequest.m */; }; + C5066C4DEF6536FD0EFF1FB8817B580A /* GULSecureCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = C6F70D4FA6DDFC1F1BE8ADAF97E4F5DF /* GULSecureCoding.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C51EBC40CA60F7415E1F235A49C93B24 /* FIRVerifyCustomTokenRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3225C5DFD5EEFAA06E0C3E77905A56EB /* FIRVerifyCustomTokenRequest.m */; }; + C5865C2AB34F73318EA74F04C54FC85C /* FViewCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CB21872684931D690D8AB43AC75C1930 /* FViewCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C5935896621D6F05F9FD8E9DF0C87D5D /* FIRGetOOBConfirmationCodeResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 67F83985ACA93737DD4D45DB6C0CA19B /* FIRGetOOBConfirmationCodeResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C5A8251BA3C2CF37D84FD68E9C153F0A /* GDTCORRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 280EEC179686C8D6A48F523385E2A95E /* GDTCORRegistrar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C5F616D8FD671D74D087831CFD3DA72B /* FServerValues.h in Headers */ = {isa = PBXBuildFile; fileRef = E708ADE62264AB03AD82509CD7E587EF /* FServerValues.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C6178D7F669409CECF25B71C2FB85B35 /* FBLPromiseError.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C7959E841ED9CAC4E3DFABCC07D4C93 /* FBLPromiseError.h */; }; + C6183ED0C750FF37035A050E3305B9E8 /* FIRAuthProto.h in Headers */ = {isa = PBXBuildFile; fileRef = BA00DAB93EF0A75C56ED6785FACD5EF3 /* FIRAuthProto.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C67CDF58259FE270848654F0BBB62D7A /* FValueEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 39ABF5B68E7A7B653EB64EC5D2D49DCD /* FValueEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C6CDDBA91529314706706F631480131D /* pt-BR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0735B2D4D87BB62774F7B9557FBF231F /* pt-BR.lproj */; }; + C6ED392FABAA1A8D02E565FD8A52F9ED /* FUIAccountSettingsOperationSignOut.h in Headers */ = {isa = PBXBuildFile; fileRef = B11DCFFDC5B68C637EBB08CCE356ADFF /* FUIAccountSettingsOperationSignOut.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C7289C4F97B6F1A1FB5A7ACFE2138B8E /* FIRInstallationsIDController.h in Headers */ = {isa = PBXBuildFile; fileRef = 45D210693C8C1852BEDCE2218C997AB2 /* FIRInstallationsIDController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C75EECAFB762933254A481B1087679CA /* FUIAccountSettingsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DB0CC50DFD83B710854E5FB52D9DA568 /* FUIAccountSettingsViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C760F013C47E323D4C9D3E1FF5E34338 /* OIDAuthStateErrorDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D4AF8B6EB8F9379CB8F2631DF57FF2 /* OIDAuthStateErrorDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C77314526A32BBAFB4B100AE8C709BDB /* FIRVerifyClientRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 41AB484DC0B19FB371A44E3934FCC0AD /* FIRVerifyClientRequest.m */; }; + C7732831B97DD10B28ADD656152C62CC /* FIRAppAssociationRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = BD30BDBFF431CB4399110E9416A8E470 /* FIRAppAssociationRegistration.m */; }; + C7EC59015485DECE33004C2FE3A8C271 /* FIRGetAccountInfoRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = F06F4E8D581CDEEFFC49BC1FC11DA980 /* FIRGetAccountInfoRequest.m */; }; + C7ED48AD37E5AA33E5D1A0C9EF266B2A /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 156A0CE6C28B38095AF9138DBEE5A713 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.m */; }; + C8155934825A976568562F6065028BF0 /* es-PR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = E54A58182BF6AFB5DC13921079ACA542 /* es-PR.lproj */; }; + C83383E1E837E12F876C0C8DB2F62683 /* ic_visibility@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0594A0CB5786656C000F34DF38D7548E /* ic_visibility@2x.png */; }; + C8444B46C6A809B8F5FF7E693B527A18 /* FIRCreateAuthURIResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 609ABC8D27C7BECC6DE50BB8016F27BF /* FIRCreateAuthURIResponse.m */; }; + C84C5FF8647958F76E37CF4871A38F2E /* FIRVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 676A757F81831B5D12A3413072F772B1 /* FIRVersion.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C8940D872F904B13AFA6FCCFB7E34D6A /* FIRAuthWebUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 477FFB4052347BAD985B3A94763834BC /* FIRAuthWebUtils.m */; }; + C894562B59FED9FC11755DA0F9CE9CD9 /* FirebaseCoreInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C02CBFECE78F11F07A8DC5E7561F36C /* FirebaseCoreInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C8947E4BC71FAD4A19AF510EE2AE1106 /* FIRGameCenterAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = B790DE03DD206859035C01A0ECA835C7 /* FIRGameCenterAuthCredential.m */; }; + C8A036DE5E750CE1A6340BE3DDD1633B /* FIRStorageListResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 2707F538B792760E9D23053698344742 /* FIRStorageListResult.m */; }; + C8B2F117CECE081D514EC94EA9F6E8E1 /* port_stdcxx.h in Headers */ = {isa = PBXBuildFile; fileRef = A54588AA46CA9135DA6EA1DF67064247 /* port_stdcxx.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C8DAE6E2DD7B93A2FB29F42BFEF482B5 /* FTreeSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1888721E3588FD46C7845A8A58070079 /* FTreeSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C8E7FFDEA70D91218F9E8A3A58E244A5 /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = ED968492E27C084864021919F783D1FF /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C8F9B76172A394266A64653451388E2A /* FRepo.h in Headers */ = {isa = PBXBuildFile; fileRef = AE90B3E6EEC9E3BF861BA8A809F7298D /* FRepo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C91366CD1844F63F6E7D9B1CF2850E1A /* FIRRetryHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D6139A789A449EA83DA37F5C9FF5DD77 /* FIRRetryHelper.m */; }; + C932A62D036F33894100D269A814A809 /* fa.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 27D4D33D864D9FCB96217A3F5BE9F5D4 /* fa.lproj */; }; + C93A44CBAB00C3210C4E6DB9AC0B3BD8 /* FIRMultiFactor+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = DE8F826E478831E2D720397A11BCC6EA /* FIRMultiFactor+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C93E85DCD5DFF7331EA4DC662B138FCB /* FBLPromise+Catch.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = E62BA6BBCD5F0BB2FCD80BEF9750D13D /* FBLPromise+Catch.h */; }; + C979A1A2ABF7694CD428642DA16BFB49 /* FIRResetPasswordRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0BE7E74ED2EBA52D88C5CDED4BAA14 /* FIRResetPasswordRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C97EA22722198678BB6118A5A2B6417E /* FValueIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEE1F42C1FC3226D38F0A8043D355D4 /* FValueIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C98A68B8E580F53EDFC270000666AB9F /* FIREmailPasswordAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = C56E3C6C0454607B87EA00A5D33CAB73 /* FIREmailPasswordAuthCredential.m */; }; + C9BD79A50C9EC3E798D8EA9743FEB144 /* GDTCORPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = EB55F12741576DE36520DDEB0C6B041F /* GDTCORPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C9CC4D4690E20E77B21C7E65825BEF86 /* FKeyIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 60D6EAE2214B51D9C890BE3365E0543C /* FKeyIndex.m */; }; + CA21C68AAD82AECD4E74D178D22C4BB9 /* GDTCORReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 7941AC0839A2D5B716F6C262BA452CF0 /* GDTCORReachability.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA7959B4932ACE1F28251FF9240F03D4 /* table_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1B2164BDA4D418A43841726EE9530F9B /* table_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + CA9D5CCB80E9B6BBE4FA9901D84A22FA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + CAB775B9C2BC54C3374267A5CA7BC051 /* FQuerySpec.h in Headers */ = {isa = PBXBuildFile; fileRef = D55CA217A8FE4CCD968B2FB20090140E /* FQuerySpec.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CACB518800D6A8DEC167FDF3F2F4CFEE /* FIROAuthCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 91200D0F48E695F4F2B5024B2FAA9F80 /* FIROAuthCredential.m */; }; + CBAC799C647E901E8584AC832E9C9B95 /* kn.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 383473E33BC32486A7A364A9BB0E95C7 /* kn.lproj */; }; + CBB680E6A640B03ABF43740C90CFA7DB /* FIRAuthProtoStartMFAPhoneRequestInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A0147206768735137648B732ADD53C /* FIRAuthProtoStartMFAPhoneRequestInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CC19FB26013C3F6D3D32F7676D1DC84A /* FWebSocketConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = AA6836C316894F3DD346893242595932 /* FWebSocketConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CC1E613809D4F1DEA773CB2CFF7E7E7B /* da.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 40BE96E1BFC9CE018C8D910E77FE05E1 /* da.lproj */; }; + CC672DB8071D00ED15A3C4884A266FFE /* FirebaseCoreDiagnostics-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F5524306327B8BA3131DB42B97A17CD /* FirebaseCoreDiagnostics-dummy.m */; }; + CC764DFBDF08AE6D71C23549529B6B17 /* FIRMultiFactorResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 875E1AF5B72E29DF5D842CD418D664AC /* FIRMultiFactorResolver.m */; }; + CD064F8796CA71F2E8E35786094917E4 /* FIRAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A3DAD5C415A8443A0DA97DCE4BB1C5D /* FIRAuthCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CD113573D4CC942C9C7C59F3B33B6A71 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B2F5E8C7D0001EC52275D753C23D8D0 /* FIRLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CD87F97CF807919B1A53E9A690E81C34 /* FIRStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C8947AB7BD466CCB237F6F4D68045B0 /* FIRStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CD8B0139FF974740C64897277783C36E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + CD930D588F6D49757B2D862919EB92E1 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 81B6701477B6C985CE39D787B599F110 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Private, ); }; }; + CDAAB6F16FDC0E93A8DC7C910853BFD0 /* FIRAuthKeychainServices.m in Sources */ = {isa = PBXBuildFile; fileRef = 993295ECC4A249DC7D75827B7832BFAF /* FIRAuthKeychainServices.m */; }; + CDE4F12CC12B5CFFBF4D04D7575C1F13 /* no_destructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 385F5602994D5DE9145DB82DBDBBECB8 /* no_destructor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CE53C8C76885412AC967D02641CE4994 /* FIRSignInWithGameCenterRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D06E70882D19FEFCE28914350700F23 /* FIRSignInWithGameCenterRequest.m */; }; + CE83BF42CF2A3D4810EBCDA1ED1C3A23 /* FMaxNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D16DC9E195D3C24653FD42E36D93874D /* FMaxNode.m */; }; + CEBB8718889E7FF3DE7599F23AC5428D /* GTMMIMEDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = F060A463E10E778840180D47DF65B53C /* GTMMIMEDocument.m */; }; + CEC0F9D226439EEE39388C3CEE8EC459 /* hu.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4C33F929C488C2621B9F88ED675801ED /* hu.lproj */; }; + CF2CEAFC127BA38E7D6F1AC771BBA3BC /* es-CL.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 3F35FE6C627EEBD84D320623CBC3ED59 /* es-CL.lproj */; }; + CFF8F6CC09FACC4F1DCF0435BD33315B /* FirebaseInstallations-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1072480B6864673EECB3B1CB257C0283 /* FirebaseInstallations-dummy.m */; }; + D00667D5C422B0E68D072FC6999ECE75 /* FIRMultiFactor.m in Sources */ = {isa = PBXBuildFile; fileRef = 846FC1E466FBFE0D850CD2366D07FD41 /* FIRMultiFactor.m */; }; + D04C4A91B83601CEA9DE9B0555F3D812 /* FTupleTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 716DE49C140CA622BFAF92044E4F1E02 /* FTupleTransaction.m */; }; + D0625A38CCEB493DD9514C5C3CD858F6 /* FNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA966424292F2B2B3A4A968426A30E7 /* FNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D0AC059F8F557C30AF3AC65DF729A21C /* es-HN.lproj in Resources */ = {isa = PBXBuildFile; fileRef = F2036DCCF9E03B57FE8FFCC80F813155 /* es-HN.lproj */; }; + D0B6AB2EA69F70BEEA48705B4523C6AD /* dumpfile.cc in Sources */ = {isa = PBXBuildFile; fileRef = 12A895F05CE634F89A21DA41783A9423 /* dumpfile.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D0E7C9A19C43A52F8052381B1D72C5A9 /* GULLoggerCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4255E63440A44CE02AF3070690D0C948 /* GULLoggerCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D14BEE9AC94984CAA75B85F9002039DD /* NSData+SRB64Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D96CCF8A1C3B80683E8A3C1767636D2 /* NSData+SRB64Additions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D153992C6E00A3A73A591420044ABA6C /* dumpfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AF57F015004BABC4B46244296756737 /* dumpfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D2046623AFEE603E261E417720B645A2 /* FAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E11AF46771013BD558C58EA9770182 /* FAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D22F32A861CFB1A862A507A81552ADF6 /* FUIAuthSignInButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A80721995C6E55BC9F26D235F75157BC /* FUIAuthSignInButton.m */; }; + D27E7F9CEA4834A3C5CD122F3DFCAEF4 /* fil.lproj in Resources */ = {isa = PBXBuildFile; fileRef = A77908716A340BFE5D8D34EE22B8A578 /* fil.lproj */; }; + D29645BA2B207B4B26F99D5359D81D3F /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 861BCD20A2A3B56F580C7A5CA766DF8C /* FIRInstallationsItem+RegisterInstallationAPI.m */; }; + D2B21F4E895FA7669B4F35F01AF25C53 /* FUIAuthPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E2DAC755661CCCACE7BA1813A316E3FA /* FUIAuthPickerViewController.m */; }; + D2EDC1BCAB13474B206034EB856BC95C /* FIRComponentType.m in Sources */ = {isa = PBXBuildFile; fileRef = F2AF2A78A3B183DE0016FB7675B21129 /* FIRComponentType.m */; }; + D30D073687B9EB2E598796EE7983B567 /* FIRInstallationsIIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F86A1C28C6AA54FE5D0809FF096D7FA /* FIRInstallationsIIDTokenStore.m */; }; + D366A214F17917F15BD2DB071E2121EB /* FUIAccountSettingsOperationUpdateName.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EDAFAAD07C262D444664C5BD399E6FC /* FUIAccountSettingsOperationUpdateName.m */; }; + D3D352E4ED4369AF438849A9EA05E907 /* FIRDeleteAccountResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C18C1536C6548F5BB3AE6687B9A6CA /* FIRDeleteAccountResponse.m */; }; + D44CD3D86EF04A05D44A13F1D20D3172 /* FUIAccountSettingsOperationType.h in Headers */ = {isa = PBXBuildFile; fileRef = 6747BE4442C95908D4D28E8D1ABFAB76 /* FUIAccountSettingsOperationType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D497442708E5489B523783EAF825686D /* FIRMutableData.h in Headers */ = {isa = PBXBuildFile; fileRef = A81FD5C759061AA4B7F4E981E801C9BB /* FIRMutableData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D4D9E1B57465298ECF4CBE859C5DCC8D /* FIRAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = ACB7AE213B5C354BC61016F4F3AA5E23 /* FIRAuthProvider.m */; }; + D4E2151D071B68DC675553D730F67D81 /* es-PY.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B530A33CA1805EF305BEC939BCCF6E7D /* es-PY.lproj */; }; + D4E43B95AA2B76BDEC6B97B152F00463 /* OIDURLSessionProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF11B4252EB3995828F722EF9E7BB66 /* OIDURLSessionProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D4EDC0B95F72E25E7923D15D0B068EA1 /* GDTCOREvent_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A149ACDFEA3E4EA95378607B77D3B83 /* GDTCOREvent_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D52132175ECC09152FD6B624A676EF49 /* uk.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4B57B1D12A80733844C26CC43FC19593 /* uk.lproj */; }; + D5271BC47C266B60022061ABDA79E977 /* FTupleObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C8A0A0BC4CDBE2A71CCF4AF70BABC39 /* FTupleObjects.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D53FD8331772F8F748AE94A788FEF452 /* FIRAuthAPNSTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C22B8910D6EF1F33FCF463C140B9FAF9 /* FIRAuthAPNSTokenManager.m */; }; + D5943A24A39C872D8DB5EA95314936FE /* FIRMultiFactorInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DB6D2539EA7C1522AC8F8066C70BDAF5 /* FIRMultiFactorInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D59E573660F805F91AD5AF8E75A5F087 /* FIRStartMFASignInRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A6ACC2CFD2255923C22F0FAE78CA8F2D /* FIRStartMFASignInRequest.m */; }; + D5BB5726B3BF325BB43EB66FB9B682BE /* nb.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 10A31E89F0E82B96B1774125C4430CCF /* nb.lproj */; }; + D5CCA75FA6DF1657EE59A5D11C1059D9 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 99E2BC6EBB91C9FFC6F7A11D13DC86AB /* FIRDependency.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D5DB4306E33312DA4BAF9D6295BA225D /* FCompoundWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E9E8BC8EA3AD45E32FC2E6FD0DFAADB /* FCompoundWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D619BB0AFDF07B688B5F1EC9D28CBFED /* cs.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 05FBF2C6D14E46A75180F9E7C78B1A5E /* cs.lproj */; }; + D6283E19F826431F56EDA36354B77011 /* builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = CE95DF51DF0284663E849AF264C11DD3 /* builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D68C650D4605745F4963E990CA7D3547 /* GTMMIMEDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 98C64CF03F4D64D5309F6FFA11432FED /* GTMMIMEDocument.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D6CBB208F35FE6BFFCCE18FD6DD36F28 /* pl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 7FAD4119D663241EA3AEADF1D7CE00C5 /* pl.lproj */; }; + D71485771BF25F5E3F6FD7A50DD21EFF /* FTupleStringNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B97D7D6E5E4BC068C64A9517329F59DC /* FTupleStringNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D805219A599D300ACF0D2948B3C0D2C1 /* FIRGameCenterAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 70C7B1A3C16EB7A855387B627E028E99 /* FIRGameCenterAuthProvider.m */; }; + D8145466BA46014F7375DC27A5A1A06A /* FBLPromise+Race.h in Headers */ = {isa = PBXBuildFile; fileRef = C90626A1C745B85C9BAF1B2F0D9A7B81 /* FBLPromise+Race.h */; }; + D8450B6C370059F67789E7EC71A2981C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEC5BAE613C9C504615D4DFD6BA5F32E /* SystemConfiguration.framework */; }; + D87549BF6D8F527CF351E13326FCEF21 /* OIDExternalUserAgentIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BEA2C64BB6137F4C8D76D2555CD2590 /* OIDExternalUserAgentIOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D88025F2C3B8216079E481F8B98AAF10 /* pb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = E0A5631CCB6A4F742557909BE284FBE0 /* pb_common.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D88EBB20646F074F346F2601E0D753E1 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = A59B1CF1D3E7FC2F9080D57916333E55 /* pb_decode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + D89C53911B9E13A27CF080ECB80A9C15 /* GULSceneDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F4DC6177BD16CE479E33E760B8781E6 /* GULSceneDelegateSwizzler.m */; }; + D8F4D4105D327D9DD02B64983C266ED2 /* crc32c.h in Headers */ = {isa = PBXBuildFile; fileRef = CA29C0CFDAD423D0106AAC1D67A0170D /* crc32c.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D903BE8C04492B3680081B4D9165C63A /* ca.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 77AFF048E9D11813E82960D3522E228C /* ca.lproj */; }; + D90A3C067FE031487AD6F53979803AAA /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = EE75160016ACEC2C076DE682CBFC27D7 /* OIDEndSessionRequest.m */; }; + D934648E3E76E7B84B8DCD0CAFA8AE30 /* FIRFinalizeMFAEnrollmentResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0342C0DE83E41409C0FC91022A091B /* FIRFinalizeMFAEnrollmentResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D93A68811A2AAAF52A93D0C215EEB390 /* FIRAuthSerialTaskQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F0FD4060063C5168EA8438027D27297 /* FIRAuthSerialTaskQueue.m */; }; + DA43EE7F5E4EAB59AC3F865E933FDBD1 /* FPendingPut.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D4712F06B0944FE3AF1EE789281B047 /* FPendingPut.m */; }; + DA5BB3CB6F30F8382EB6BE0797060DA6 /* FIRAuthRPCRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AA3BC8FBC301E1AD271B8BC56131017 /* FIRAuthRPCRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DA64FFAE7EC53366D2CA6B3BA8B81C86 /* FWriteRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B732645135CA8B3E7FA00F9C6EDB77 /* FWriteRecord.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DA8DC828D080054BAE395DC6333A1906 /* FUIAuthStrings.m in Sources */ = {isa = PBXBuildFile; fileRef = 376319FF589FAE9CFBD2895D95DB64AD /* FUIAuthStrings.m */; }; + DA8E5C7DB11C5D8B3F1C6713C4A2245E /* FIRVerifyPhoneNumberRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 105D55B1653C85994022CD7D23E05D05 /* FIRVerifyPhoneNumberRequest.m */; }; + DAC538082C4126C06C1BFE1C9A257981 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + DAEA3C69527F4D08C2FC1597D3F0F5F7 /* FLLRBValueNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D5C4CD5C56186305607180E61C480F0C /* FLLRBValueNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DAFA58E57C7E58B3C33229A7B383683A /* FBLPromise+Then.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 925C41F8B9D85ABE6F2C5D11D6784234 /* FBLPromise+Then.h */; }; + DB446AF711F320FC5D625B70E233071E /* FIRSetAccountInfoResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C199C6C880F5BBB8AC4A31DBDFD42AE /* FIRSetAccountInfoResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DB562F789B54D8C9B978FCE4633D1D3F /* FCacheNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DB63E002E064E3C55D0852F18F0139B /* FCacheNode.m */; }; + DB72A4C0F3842894EE3485E3B9DEF3CE /* es-PA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 32286B36029E0A0C5EF3CF7FACFDE828 /* es-PA.lproj */; }; + DB80588663B066BDCEDE84ECD2BCF5F4 /* FTupleNodePath.h in Headers */ = {isa = PBXBuildFile; fileRef = 24191B50B213697BDB0A03CD396569F7 /* FTupleNodePath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DBA3198737B9A39069EE86B647EA0E5C /* GDTCOREvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 766A6826F51D60F3F8BF5907E443E340 /* GDTCOREvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DBB9A02097B659853F4B886DB3B20635 /* FIRVerifyAssertionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AB447E9106C479163FEB96B7765FE05 /* FIRVerifyAssertionRequest.m */; }; + DBBE4B8E6203C75F1169240E0D3CB058 /* ko.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 904ACA95784DB45F51C8EA34D83966A8 /* ko.lproj */; }; + DBE525E02DE2D94E18A9DDA72F7F3BEA /* GDTCCTNanopbHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD6E35DDB2EE9EE7ABB6F3C84BC29B5 /* GDTCCTNanopbHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DBEB33230CB517C515DB56798A8C9231 /* FTypedefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 50678D93A7A086BDB66C72F4A47CC647 /* FTypedefs.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DC9289D6C939B88D93E2144AB1FE45E2 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 55921E5AC59C99C61E45F4771E6881C9 /* FIRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DCA24C8C646B26DEE228BCC7F3B19BC1 /* FIRPhoneMultiFactorGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = C74F354DE76EFF3D897FDE22F1864112 /* FIRPhoneMultiFactorGenerator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCB70A2DA3308E442CFDA42287EB8460 /* GTMGatherInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 73A3621A5DB4EDBF660C671792E13759 /* GTMGatherInputStream.m */; }; + DCC571B18FD701B48BBBCDE7BB8980ED /* FUIAuthBaseViewController_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 31D97EF3B9821B7290206D1CC3E1440B /* FUIAuthBaseViewController_Internal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCF1D766DFF35DAE3D5F3AF6D7387339 /* filename.cc in Sources */ = {isa = PBXBuildFile; fileRef = CEFFC93E93A7DC5787D5DF680C4AE458 /* filename.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DD19B6905B7D7FA862FFC69BFD07029D /* FIRComponentContainerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D90122FAE5E38A814CFE89844E5604 /* FIRComponentContainerInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DD25EFCEAD905565F239CB758E249371 /* en.lproj in Resources */ = {isa = PBXBuildFile; fileRef = B9DB9D346A7C30019219602974216E5C /* en.lproj */; }; + DD81DB4F830987026CB2FE2029C65D4E /* GDTCOREvent+GDTCCTSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = FBC075A76606AA21175616AD5D5A2818 /* GDTCOREvent+GDTCCTSupport.m */; }; + DDAD7E2134D598D2FC92464099AABACC /* FIRDatabaseReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A9978BE5C233D164CD7C226805A2D0 /* FIRDatabaseReference.m */; }; + DE23788919FF5136AC4B77F9B29FB4C1 /* OIDFieldMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EB529903C3343CDA096444732E78D38 /* OIDFieldMapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DE5F0C4CAC8F5CA01F36125D1B5A6229 /* version_set.cc in Sources */ = {isa = PBXBuildFile; fileRef = 39FCF7E01DE23C18562782A5899B4D4C /* version_set.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DE7A77D8981731B141BFDA6941F13A4D /* el.lproj in Resources */ = {isa = PBXBuildFile; fileRef = FE7B98B1A5BFC14EF81EFCD319A7C848 /* el.lproj */; }; + DF0D854E2FCE940A60925487FE56383F /* FUIStaticContentTableViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CA4F38D6112A713AD3F9140E7F68026 /* FUIStaticContentTableViewManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DF36D69235F7E6D1FDB363A72474DA71 /* FUIAuthTableHeaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CA945041134FF42600B03386818A62D /* FUIAuthTableHeaderView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DF469B7659F9DFF3166AB7C7C8887D6C /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = E0DAEAF751077AFB2147091AB7D8CEE8 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DF5C7C988590C10EF45C78A8D4167D79 /* ja.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BC2B894E2BDEB2C236F169221286AD5B /* ja.lproj */; }; + E00843404BB41C185A3A63CCAA29CB08 /* version_edit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F25C53B0BE44DB7561861818BF846CF /* version_edit.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E0454BD85399837BAB438DABB3F6E60C /* en-ZA.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 6024FDADF987F2A905E3FABFDCA3FAD1 /* en-ZA.lproj */; }; + E0E45289D2F45E1803D45D844CC5A112 /* FTrackedQueryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 180AD6EE5C9A774D35CCC09E2C3643B3 /* FTrackedQueryManager.m */; }; + E0FAC15F4F36C52260C7EBBCCF82F9BF /* GoogleUtilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B05C4EB3F8989AA897BCBBBC215D6AA /* GoogleUtilities-dummy.m */; }; + E0FCD66EBDA02C684788F94AF3B506E8 /* FIRStorageErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 71548566AA12411F1169B351463A8EF1 /* FIRStorageErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E1D083BEA9134178F042CDFCFC19B6ED /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + E2007B77352C68972421B9413734BD30 /* mr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 9A23A0C9B7AC4E516824E1155565BF31 /* mr.lproj */; }; + E200A7C70F0C4C52A501EB305742E8C8 /* FIRSecureTokenRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BEF95068A2B04D39985E4D2821BDE9E /* FIRSecureTokenRequest.m */; }; + E236C734524700EC96663DB6E943ABF8 /* FRangedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C891BDA225BAD436CEF7AF7F1695ACD /* FRangedFilter.m */; }; + E2DB411F4F19E4999A6994BE078B24EB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E942549C86F57C477E3AC759C80C513 /* Security.framework */; }; + E369EC0FBFCF48A9423F2564B29EF001 /* FIRMultiFactorResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 5604269047012A590F82880FF4FB18B8 /* FIRMultiFactorResolver.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3967DFA258F8BC1453EAC67AE9310F7 /* FUIAccountSettingsOperationUpdateEmail.h in Headers */ = {isa = PBXBuildFile; fileRef = 66572644FE511ADF1DD46C07C47BB895 /* FUIAccountSettingsOperationUpdateEmail.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E3B32C12184BD887E6687F73097489FA /* OIDRegistrationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CE9B81EED1EAD62E147C5B7DE06E7DE9 /* OIDRegistrationResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3C8164AB15FD3E49F9596AB0D0B864E /* FIRTwitterAuthProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB00CA7F1B74B70E55D98ACA2FEE9E8 /* FIRTwitterAuthProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3CA70647D730C7F4AA6E803A8B7D45B /* GULNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C3177C16671C84C8825F706F9F17A4E /* GULNetwork.m */; }; + E3D6A62063F2E24045C0280E14A53AC6 /* FIRDatabaseComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = F05F10A2D2CB88848EEE94089569B421 /* FIRDatabaseComponent.m */; }; + E437D1AD71F866D6F132DE2D7C76106C /* FIRAuthTokenResult_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 147ABC58AAD1BAF83AAFFD3ED20DF9CB /* FIRAuthTokenResult_Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E43E3D08B8736D45D8E2BAB690D16EAB /* pt-PT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 752204D20D33393B7F9DFE09AC0A6117 /* pt-PT.lproj */; }; + E443ECCBA3ED60473D807F189C63A0C6 /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 74A271C15E69BBCEC463F5F670300BA1 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E443F553AE1013EE57D66FB6F366284D /* FUIAccountSettingsOperationUnlinkAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = A024BF1A97EF24A2E139DAE4E26A7246 /* FUIAccountSettingsOperationUnlinkAccount.m */; }; + E469D24D743C3E4652BF03FE14A930A2 /* dbformat.h in Headers */ = {isa = PBXBuildFile; fileRef = 678B1223F2BE90B1D127AB412F334E22 /* dbformat.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E47E4F87861D63C31906084CC3D02FD8 /* FView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EB1396AABC1139BB96C6491579BD8F4 /* FView.m */; }; + E4BF0A6D197372622BAD119250803FE0 /* FLLRBEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 69734D4AD914CB4493F17184D49AB7D6 /* FLLRBEmptyNode.m */; }; + E538ADF57675483F5E819544E3196EB3 /* thread_annotations.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EF93A47B978CDA02A82640CB31708FF /* thread_annotations.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E543AF0428A65642BDAEC31855D3F617 /* FParsedUrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D643088290FC363A90F847070973A68 /* FParsedUrl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E5546DDB0E178716F78C18D720DD82C6 /* FOverwrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AA9752886E774984AD2D35449B849E7 /* FOverwrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E57BEC68DB3A443D9F6C5F47C4654036 /* FCompoundHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 05767D0A7CDA76A6FB22D66FA268BFF6 /* FCompoundHash.m */; }; + E57C46D80106AD4F7D13F5DF94918E36 /* sl.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 7F9AF4AD8155223C8FEEE6032B169F66 /* sl.lproj */; }; + E5BEA8D45FA0FF2DF302A9608B9BF67E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + E5CE931AE49A8D2FF990047880BDDA39 /* FBLPromise+Do.m in Sources */ = {isa = PBXBuildFile; fileRef = C78C74720DE09E30B23A6F9C9B6F5242 /* FBLPromise+Do.m */; }; + E5D3A5F9BD84F3C5F7C52537823DDED5 /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = A081B6423331628EACC4D7A73AE127F1 /* random.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E5D7F12887D02AB5D3E9AFAD1726FF76 /* FBLPromises.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3097FE693219B2669E5404BF817BDBB3 /* FBLPromises.framework */; }; + E5D8C8EEDD4793627F5DB60138E9661D /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = E8912EB183AA4629889505B7BB5CAB6F /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E5D9CA3A8FD14545EDF531018A012713 /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 618B1E5DFBEC073ABD03719A3CBEC5A2 /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E61992624EC5BDF25D2341D1074E43D2 /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3082E6493AB93A9C2593DFF6F5506755 /* pb_encode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + E649DFA32A6BAAE9A51F363C9E602C2C /* FIRAuthAPNSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = F909B1A1A39DA32987EB786BA0FF883E /* FIRAuthAPNSToken.m */; }; + E679F946FDCDB8FAD74B2E59B9310D73 /* zh.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 77428BF49AAD71B811C8A6049C09E441 /* zh.lproj */; }; + E6EEB032CC491EC20EC6B90738C89A8F /* FTree.m in Sources */ = {isa = PBXBuildFile; fileRef = DE334E8A8F2607F9F0CF675028E6CB9E /* FTree.m */; }; + E6EF4479961ACABE1220DA2BAB584C67 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 562417974B48784FF00BE78597B8C019 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E76504AF0FB9100EA2A0F85327D531FB /* FSnapshotHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 94186DE3D7783AF3D30A3B3D37ABB931 /* FSnapshotHolder.m */; }; + E76B7C34229CFB62ADDDEB8B33806449 /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 17D499F429E7B17807816EF3C2257723 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E78B4185E629DF134AA7A3B601181F03 /* pt-BR.lproj in Resources */ = {isa = PBXBuildFile; fileRef = DCE3112310721644BD336BAD8E71CECE /* pt-BR.lproj */; }; + E792064CBC904A9CC45C89A4D95FA7B9 /* uk.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BE57096B74561E4E5589CC94B228D138 /* uk.lproj */; }; + E79BC35F5EA6D578733825721321CDB0 /* FIRStorageUpdateMetadataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 764B12FF08FBAAAC81693F5927AEABED /* FIRStorageUpdateMetadataTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E79E1DEEE6343F54BB7C88B388F1BB27 /* es-MX.lproj in Resources */ = {isa = PBXBuildFile; fileRef = EF27A4D04F2D6D69190C3B0E898A3BA0 /* es-MX.lproj */; }; + E7BE6F8A2635F39A83DA391D1ED69423 /* FIRFinalizeMFASignInResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F990D243683DB1B69B7DD45FE31E6E7 /* FIRFinalizeMFASignInResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E7BFAEEA08AD6F53650709C173E285EC /* FSyncTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 24FE7022564CEAD1E6D3E5E23E421FC5 /* FSyncTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E8A95FA1B53FA8DCA22749DBE0B3D245 /* FUIAuthBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 953494A16560D8217BD92077C174DEA4 /* FUIAuthBaseViewController.m */; }; + E8AD283782868B5C6CB7D49A0914F12D /* es-CO.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 2506B650F36439620CF54F5655EBDEDA /* es-CO.lproj */; }; + E8EC7708E95120E14E2961DA89E96899 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B8C3ED9FC01D4F3116710E7ADBBBEA /* FIRErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E96A582B38DBF7513BFCE5A26FEDBD98 /* GoogleDataTransportCCTSupport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D1522D9A59FBC064607570F12367743 /* GoogleDataTransportCCTSupport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E972E1D830854279B5B576FFF129B70B /* FUIAccountSettingsOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 03299E70B14A8CA0CD3B288F7D43BE4A /* FUIAccountSettingsOperation.m */; }; + E993D71D217E1527F8F37ADB3949E862 /* crc32c.cc in Sources */ = {isa = PBXBuildFile; fileRef = C24569803038905A315E8886A49F56C5 /* crc32c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E9DDAA3C7E1E79D4C9C6F95B2BCCECBC /* cct.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = EF9FF3D787B018F3B85A15958455551A /* cct.nanopb.c */; }; + E9F723EEC8516CA7A483BA6EDC50D8C5 /* FChildEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F3F1CA3592AD79DF78A58DD1CCFBBAF /* FChildEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA278C7D9EB69B68733EF68A0C150345 /* OIDAuthorizationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 376756AE54DA1CDF00DF5DE0090FE3FF /* OIDAuthorizationService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EAD4D728BBB0FA93E3B229608EC26BF0 /* FirebaseAuthVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 218CAE055A0262CE3E2519316FDB660B /* FirebaseAuthVersion.m */; }; + EAFB49066FAAAFCCFB16E7FF666F1D21 /* FBLPromise+Recover.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 169EC26D74379B8E784D2BAD7F05FBAA /* FBLPromise+Recover.h */; }; + EB1B7B371D9E895DF852FB63CA566887 /* FIRPhoneAuthProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 5440B26AAF05B19A6349A85F31249BF6 /* FIRPhoneAuthProvider.m */; }; + EB7BCF5DD7AB0F1D2738BCAB700907EC /* cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = BB721B72DF6ED457D6DA175690F307F3 /* cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + EB95AAE8ED1D72BAD0B6FF407F09C5AC /* FIRUser.h in Headers */ = {isa = PBXBuildFile; fileRef = 76653C0C50EDD5D4C16513CE8BEEC454 /* FIRUser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EBBF6C1E5FA3828EB3EAF8F6F2E1FFB0 /* FIRVerifyPhoneNumberResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 19DF54507D0D63DE4425E3FE350B9832 /* FIRVerifyPhoneNumberResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EC1E607B0EEF07BB64F476B9FB5A4FFE /* FirebaseInstallations-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B01F7EDFE796ECCD43987D342ACF9799 /* FirebaseInstallations-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECABCEA0F748B3932FEC95A7ECA42B53 /* FUIAuthPickerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C045B91D80FD301D382461F3767A8CD /* FUIAuthPickerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECB05ACB39725CA8A0B7190E26BC1E66 /* FDataEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 504B0D1BEED943ACA979474FA55362FE /* FDataEvent.m */; }; + ECCA642BC105435BB9D30D8683FB4F3F /* FDataEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = A71D66ABEC259E383B47228B948294EC /* FDataEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ED0E118623AAC51CF9F1549798CE585E /* histogram.cc in Sources */ = {isa = PBXBuildFile; fileRef = ACA0CE3201D296FEA1844CED6E9D0E8D /* histogram.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + EDA75E998D1315C52E7CBD7E3D040555 /* FBLPromise.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 10CEE0353BF9A5552A076306DA76AEE7 /* FBLPromise.h */; }; + EDE7D66D2B5C037707D24A24088DF30B /* FIRLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 8DBA967F5DF73F8FE98398812A2958BF /* FIRLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EE191018EF34395C61D30D78FED87E45 /* AppAuthCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C8F2633D88D1F74962838B253D72FCE /* AppAuthCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EE22548769A238F68DCE0A8F540C5F61 /* FIRPhoneAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B18A4515BDC97476AC776D94BEC8918 /* FIRPhoneAuthCredential.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EE329DF01337A5B2040D3D7532BEB766 /* OIDRegistrationResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = AF28C7AA75034B0E472FCB46591FE86D /* OIDRegistrationResponse.m */; }; + EE8AC38A9ED2EA24296D80E546653DEE /* FIRSetAccountInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = BB397D64A004B2E58E996CA6126F9E5D /* FIRSetAccountInfoResponse.m */; }; + EE8D546D679D2358F8C9F88AD50C92AA /* gu.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 20E3C25D260E7FAD721012E746F5ECD9 /* gu.lproj */; }; + EEBEE12CF7A3B76897339AEBF82DBA9A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + EF6FEF068B4C41B1EC133F11C985EA70 /* FIRInstallationsErrorUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 65E368CF321942CE98AAD10B26D0A07D /* FIRInstallationsErrorUtil.m */; }; + EF92363675B8414D14801D29A288FA31 /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C74BB36833DAE2734F5679B8EE2E04FD /* SafariServices.framework */; }; + EFC82375164452FAF42A5399AA60AE75 /* FPersistenceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3975E8FFC67926A0E8DD39BDCBA4B16D /* FPersistenceManager.m */; }; + F018A89489B2EA5C5C0C4687E4844595 /* FUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C64029352A35B37DDA881D4E6ACF6C1E /* FUtilities.m */; }; + F04ADA229C116F08A9AE74C7AA90188C /* FIRAuthInterop.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C83DEDF6D65FAC677439496F70A8003 /* FIRAuthInterop.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F065A5C0614E392EE29FCBB2B1948B61 /* FPathIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = D4DC8D9D0355EBB0F68A676013F799AC /* FPathIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F070482F4FE2BAB29012DAB0E39641EE /* id.lproj in Resources */ = {isa = PBXBuildFile; fileRef = BEE24FC0665340E787AA4D29456F0DE1 /* id.lproj */; }; + F08D2D2BC131436E99F047461CF3F534 /* GULAppDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 782C0B18B8A79A056DC2C87331FC21DC /* GULAppDelegateSwizzler.m */; }; + F0EDE9B2A1C5B429C5FB45DB791CED5F /* GTMAppAuth-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AAD146A75E91278F8462790889BE1D3 /* GTMAppAuth-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F108A35D5F20AAE03C47FDFC7EB8423F /* FCompoundHash.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B7105386F708B8C130FB1781D4A137 /* FCompoundHash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F113B4B95B46B980F23BC35C3C564B07 /* GDTCORFlatFileStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = E7116A9977F9F821C626236E9AF7F5DA /* GDTCORFlatFileStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F1661085F8334C84CCD5F0B646BE2B9C /* FIRStorageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EFF3A22F1C48B4980A4B052C0875FD6 /* FIRStorageDownloadTask.m */; }; + F1872FB4AA315ABD8D17466B5B226722 /* de-AT.lproj in Resources */ = {isa = PBXBuildFile; fileRef = D7BB87477E1647138F76960431BA7280 /* de-AT.lproj */; }; + F19EF42A235378A4B64C0690CCB7EDA7 /* sv.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 6109B697F6B52FD7D66B26A351F6A920 /* sv.lproj */; }; + F19FEAC355F8BD5C7A64542BF3D5AB4B /* GULSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DBFD500F6079D0B3DE7D70BF750C3A /* GULSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F23DD095353630CBE344B23ADBCAD19E /* FOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D569EBF0B43DFF73C4402B67F722476A /* FOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F246177F1215CDBE9AB3B1BB58624C04 /* OIDGrantTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = D2E9C90D84A48DE2D192DE4878590DC3 /* OIDGrantTypes.m */; }; + F26745D80A87F6DBBB617D7B1AA44ACC /* ko.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 431F138349D4FE38FA96998F33938388 /* ko.lproj */; }; + F26F91FF2BEA275801E9631DA164EF65 /* FEventGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = B6BD3FBBC2A8E810BCD6B7AD16D08BCC /* FEventGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F2A52B29F6C03BEE388842FD6FDBA9F9 /* log_format.h in Headers */ = {isa = PBXBuildFile; fileRef = FFA39FBA8960A7E7D4BE2CB4087A52A9 /* log_format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F2F69D162BDAF8035746AABD744903F6 /* db_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 49628C5F8E59FEC789DFD126F5FCB1A3 /* db_impl.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + F34348F4E358B24E8905FDA182085DB4 /* GULUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 6998105EDEDFE89C9237A903E13AA4AA /* GULUserDefaults.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F3AFF6F8C7638836D6B8F5FA0FEFFB5C /* FIREmailLinkSignInRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = B005A07BEF4B4650B74F86B0F91D2E75 /* FIREmailLinkSignInRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F3B78D6132C09A006BA59805424A789C /* FIRServerValue.h in Headers */ = {isa = PBXBuildFile; fileRef = F003A93336794A794BCBCD679CAE6F9C /* FIRServerValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3D2632F5565AFA96A15FBA9EAFFF410 /* AppAuth-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 95FA9C91714169BCFFD60B45C1E46863 /* AppAuth-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3DAE3F10176D848470A4FA1DDBA8ABC /* repair.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6B307FF8DD426613C9E87912E8096331 /* repair.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + F45DC573E9465E4C95C24C3A7FB7CA6A /* pb.h in Headers */ = {isa = PBXBuildFile; fileRef = EA45E97075132BD1F9B6009A8CD150BD /* pb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F47356F17DCDEB91F60B6E75D5767AAF /* hr.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 5A0D953E59A8DED28D3164EC06E93905 /* hr.lproj */; }; + F47BF5598DBEDEB0A44679023AFC7E66 /* OIDIDToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FA4EB3669CA064C1FDF3FDF3E4098E6 /* OIDIDToken.m */; }; + F4A86F4F47AF4ABB0A8FE4D860226B39 /* FIRInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E9941705FB79B209ED37BD90A5D902B /* FIRInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F4CBF2654015FB6A55443D30DB7C37E8 /* FBLPromise+Race.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C90626A1C745B85C9BAF1B2F0D9A7B81 /* FBLPromise+Race.h */; }; + F4E5BBECD1B7031C8F00A369BE738842 /* FirebaseAuthUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 572768369632698FD67E08A6CBE5E65F /* FirebaseAuthUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F567CD8818C2CCF71B31DC02EAAF2049 /* skiplist.h in Headers */ = {isa = PBXBuildFile; fileRef = E20B04EEB401E2EA11B710895B87E3F2 /* skiplist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F598CB205564B44BC8BC6B774DEB1B62 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = B5F0E87509D9331164A5F4D765B1A3D0 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F59EBF58D2C5254E95E44135A99D1012 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + F5E16190B9673C1FFCD855ECF2D53F6E /* id.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 65B5611A02B54AF167B839A5FB4E668E /* id.lproj */; }; + F608A36D494BD46091B61DA00A07B33A /* FIRIdentityToolkitRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A554AF875831B385C25328CECE189540 /* FIRIdentityToolkitRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F608C27330385270AB820E4A6FBEDE06 /* FIRMultiFactorAssertion+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4322D71552AD5DA1FD0A28B69543F2A1 /* FIRMultiFactorAssertion+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F61B0540638CF3C0CF02D667825D3CFE /* FIRAuthBackend+MultiFactor.h in Headers */ = {isa = PBXBuildFile; fileRef = CB61E9165D81B890E80D2A1EA5182F06 /* FIRAuthBackend+MultiFactor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F62A0C4559F60B516B8350633B5202F6 /* FIRStorageConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = F723B27C6E94B8411EC2A203BC352B35 /* FIRStorageConstants.m */; }; + F63C85CE50933EE6BDB86F9C87253F1C /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = C75B68AA4C55046DD41596EEF217E773 /* OIDEndSessionResponse.m */; }; + F677A4A964B9095056DA905477CE4F3C /* AppAuth.h in Headers */ = {isa = PBXBuildFile; fileRef = F0EB221FC3A302A1F08E0A6AE9D192CC /* AppAuth.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F682300AAA5CF33F9E4730A6199E483C /* GULNetworkConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E40F8DC8B40272B99AAE3C0E3B49D1B5 /* GULNetworkConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F69343F5F4D92D4C742FCAF11C040243 /* FIRInstallationsStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2891BDA51C2AF6BC9404F4A7B1727870 /* FIRInstallationsStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F6FD97488F8B55246A4560D09E895FE8 /* testharness.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAC46B5F4A304C75A40CC264D52033F /* testharness.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F709608E527764176D6C817068EB4789 /* FWebSocketConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EBC0578E0831E699FDC8C670820885A /* FWebSocketConnection.m */; }; + F74ACFAD0432A11A50BEBAA87995BB94 /* FPath.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D94B4A4AE84B510828A2C92D89819 /* FPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F7C22DF3F17C92D62C2E2B3FC509BCBA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A902EC22E4E7592D1507079756376044 /* Foundation.framework */; }; + F7F66C2FF8A65D04251D1547A5FB3E51 /* FTreeSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 964A6F832C7C75A9B0A0FB580C10E821 /* FTreeSortedDictionary.m */; }; + F81A555804B10264F17B159F83D45E04 /* FIRResetPasswordResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CE21C56EF37A104800F9B6C5FFFFA0DD /* FIRResetPasswordResponse.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F8299543C8A7BE4A43BDD63CD33D5057 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F4E2727B989CA69B54F7395BCF5716 /* FIRLibrary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F83A172A04A254A7884CC9C004FD0841 /* de.lproj in Resources */ = {isa = PBXBuildFile; fileRef = C5F00DE74D2EC6196997C150EB6ECE06 /* de.lproj */; }; + F88E6F2C4272A5079D67CFC2FA86DEDD /* leveldb-library-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 07EFF1CBAC30ED458104AF65FAFE793E /* leveldb-library-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F9301E64322318149AC4F02E75E9DA35 /* FIRAuthAPNSTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C5B786A2F794E5BFB62AFC684ED5B115 /* FIRAuthAPNSTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F94EDC42FB4C8B5B2EE74BB586A6AFC3 /* FIRSendVerificationCodeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 972070C5155A5F1E91B6A9DB11D2258B /* FIRSendVerificationCodeRequest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F953FD5F7471BF27A56FF74E1CD36529 /* FUIAuthUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = BD85954CCC85183D912107A4874B556F /* FUIAuthUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F9940A407864D41F952E05184B227F67 /* gu.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 0C6ED211312B3541D9CED14186669579 /* gu.lproj */; }; + F9FEE6018327821CC1B6ADDA9F505815 /* FIRInstallationsItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F4106304CD7FCBAC9D6A0DCB765AA54 /* FIRInstallationsItem.m */; }; + FA0D3A03C8925D8109897F7C79B8F563 /* FRepoInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B0ED66B3AB0DEACE07CFB743EF1AB1 /* FRepoInfo.m */; }; + FA4982D49526DA1F51AFAD759C42A1D2 /* FIRDiagnosticsData.m in Sources */ = {isa = PBXBuildFile; fileRef = 3206E36B58AC84FF7A082C1E27882B90 /* FIRDiagnosticsData.m */; }; + FA54A074580C072694058298A88B803C /* FirebaseCoreDiagnostics-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 58B98A3CF9D1D67D9B4602B856D83CE1 /* FirebaseCoreDiagnostics-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FA8004E02DFB16E6E4671AED8E96B847 /* fil.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 044E68ADDD610FF0750545E3E8E7FEBB /* fil.lproj */; }; + FA89EF3F0A0EEE0BA38EBEF25768C0F4 /* FRangeMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = 64F0158D39427082A58B66417D642EF2 /* FRangeMerge.m */; }; + FA8A2587E7695AEB9A82EA5955C49B5E /* FIRCreateAuthURIRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BCE6DCCBAC25268B5B31598C195FF5C /* FIRCreateAuthURIRequest.m */; }; + FAA959BBC36AB00E58C4CD4C0020448D /* FIRDatabaseReference_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FC5C52298AD31598C0A44EF9B2C6F44C /* FIRDatabaseReference_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FAB11BF4DE580C652061074B84C43827 /* FTupleObjectNode.h in Headers */ = {isa = PBXBuildFile; fileRef = CBB066214D917EE5CF525A00A0789398 /* FTupleObjectNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FAB763CD2C3F810473A37FBAE38A7778 /* ta.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 945357ECAD83195AA46CE7BEE8C52071 /* ta.lproj */; }; + FABE7EBD29A940330700F0EE7E959A8D /* FIRSignUpNewUserRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = AC71EF56D169FAEC6FA1922E3EDE88B0 /* FIRSignUpNewUserRequest.m */; }; + FB26C46BB811C4BABB6C953C10A05757 /* FValueEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = C01BC2C5447DFEE202AD31B17BA8FEA8 /* FValueEventRegistration.m */; }; + FB29C8A1436FB39EA84D5A2475C87C41 /* FIREmailLinkSignInResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = E94E0DEED20A943669F5DC4D7EE30AB7 /* FIREmailLinkSignInResponse.m */; }; + FB41EE932A129AF4060E44B7859B1F06 /* FIRAuthExceptionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 7705D67F509F485AE9F635CEFF68D4FC /* FIRAuthExceptionUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FB48F1055BE1DFA8C58757C1D279F640 /* FIRGetAccountInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = C76496A8B14E858B7350925B0A20A7DA /* FIRGetAccountInfoResponse.m */; }; + FB4FA7F5E98186AA970A658790FC86A6 /* FViewProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F27A7A83BC933E0BA0CF7DD8D4E4C81 /* FViewProcessor.m */; }; + FB5040342CAAF75666DFFFE139DEDA94 /* GTMGatherInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4255EAE792EEC21FF83A733F61479D97 /* GTMGatherInputStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FBBD10600C3940F1221E394969DDFBBD /* options.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED2CF6CBF8074DC1BD4979852C0F034F /* options.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + FBF11439D89D4AE4C4E7B22E4CDE2BA0 /* FIRGitHubAuthCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCE96FB03C7E2B07F0D846224B8050B /* FIRGitHubAuthCredential.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FC6E525DB59C8B750B92BFC9267D4AE6 /* testutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A6735AEC88EBDF9980427BEC3A16C7F /* testutil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FCB12EE6028E0377C6A2BF722F3AE80F /* FTupleObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = 18FDC64B1FC85B24ABB1C0364C15D919 /* FTupleObjects.m */; }; + FCD759F250B22BE7B29D01149C8216C4 /* GDTCORTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E1B0586B157A28B1F1A35C9E6783268 /* GDTCORTargets.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FCDD19997C4A4C655F8E2CCA8BE31E58 /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 61DACD2C6A7C9F8A229EF0ADE870DE2A /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FCDD595D5296BABF498C6E013D2642EA /* FIRActionCodeSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 00FF6D3534EC1D8A91F5F95AD021827C /* FIRActionCodeSettings.m */; }; + FCE66C0F139268FE64F586494A2F3357 /* FIRMultiFactorSession+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = A55165D05F5298D7EC70AC6D256E7480 /* FIRMultiFactorSession+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FD25233B55493383D6C576E1CEE7E2E7 /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DB941D9DDE37F386275A2A26D65A2292 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FD34718836DC0C3C9E44F282E8F9848B /* FBLPromise+Wrap.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = F8B0B924EF0FBA3293977F67BC3ADB6A /* FBLPromise+Wrap.h */; }; + FD40D9F5432F5551E88C9103C3361ECA /* FIRInstallationsStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = F64CE77C106A717D67E4CDE515D39305 /* FIRInstallationsStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FD4537AD06CCD6734E9259ADA0A18F55 /* FIRAuthWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E390ED7946A6255192CC662B974485 /* FIRAuthWebViewController.m */; }; + FD4946D8DC99F701B38380F998F6F777 /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FE43939DA337EF2714620503CF0ABD71 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FD981764DC1FDE7ECB985ACAD71112FB /* FCachePolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA16A2EC6DEB773205D80D76F235DE58 /* FCachePolicy.m */; }; + FDBB34D54CD027C53FAEE20803153A49 /* FKeepSyncedEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = AD0A6CCE189FE94F37994AAD4CB73A1B /* FKeepSyncedEventRegistration.m */; }; + FDD9F1ABDB62000AD4EB21C5C437C801 /* memtable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 55736272F08581E91E4043F8CE9E5C23 /* memtable.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + FDF061B03A01F2FFEB7070BCA968F22F /* table_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32286A49973172FDDFAAEF75ECA6EEDE /* table_builder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FE1E15FF3CC9A34A8747AC76D2115BD9 /* FTupleTSN.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6715856AC895328A2AEAFC8B86E640 /* FTupleTSN.m */; }; + FE7FEF31EB3953731D45A601645FBB37 /* FBLPromiseError.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 1C7959E841ED9CAC4E3DFABCC07D4C93 /* FBLPromiseError.h */; }; + FEBD9425BB41A3E32676155E656EE13B /* FIRAuthDataResult.h in Headers */ = {isa = PBXBuildFile; fileRef = CEA28D4D4EDF2349738CB345D7EAA2FB /* FIRAuthDataResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 010F07B1C767CAD81018B2270BDB1848 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 071D8D247AAD714748EAC34CD9F73348 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 0731191EEE5227426FC3E06F38030119 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 075D5B5B0C185012243AAA04E44230A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 126018A904814EA99D27EC03B05B36A8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + 1744D66CFD389BDDB1564ABB3C0CB2C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 1C22F2299104707ADE6EC1A1BC085CE3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + 28E28E2BDEE7C508774A40F5BE7A319A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C642AA10FB29936669CC269F42079C6; + remoteInfo = AppAuth; + }; + 2B2F6F4A87E5302955A2730AE4F31E2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 312219644023E298DA40F1DD75C8DA11 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 335F95B6CE168385BA93EB8B9BB517C7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + 340452A7367705D2113B5D88428CDA52 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 3542E1C31EAABD4FB4866C17CE2EFBAB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 35E3B3F7AC5DC47D4F258436E0E9E3C8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6051175E4E4C37209FBE2BF5BE4627BD; + remoteInfo = "FirebaseUI-FirebaseGoogleAuthUI"; + }; + 366053566D1F4F9AEE9DA3436BF8AC2B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 3A0F3C20D57137EA50313B27510D20A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6AE4A3D573DED275B034E20506596C62; + remoteInfo = FirebaseAuth; + }; + 44C02AF115EFCC36544FE7A86B0471E4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + 4B56396745027BC82A40601D428C27F5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + 4D25F6B4E0A10549DC7CEA156700A207 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 4E2A37CD36BD7FD428D9385A5D248C93 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4F91D2ECAC31D494531E121B750D88A5; + remoteInfo = "FirebaseUI-FirebaseAuthUI"; + }; + 525CA5CA0973E2865F15D715DDFAF804 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8627999EF1D5E93E13DAFF580DA8CDCF; + remoteInfo = GTMAppAuth; + }; + 57455EE8C938F1E79B9092051E3C2D6F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + 58327700A92C5323F432AFF59DE99969 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + 59EB9FD842075F38F65D1C01FCB87B52 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + 668B7A11F521D0EB1F41665973A46D04 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 6C26D7C9E53F52F612D00E87253D5FDA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6AE4A3D573DED275B034E20506596C62; + remoteInfo = FirebaseAuth; + }; + 6EB53DDD74D0AA3D084AA70752582019 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 71158069FD5DAC3AF5A98F3D3A0285A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + 7829C8A09AA6FE1144920B12865C4F56 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C642AA10FB29936669CC269F42079C6; + remoteInfo = AppAuth; + }; + 897E13BEF582159D0B0D986EE4B10357 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + 89BAB4E0A3FD8999A33C83637D2FCBD7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 94538A05E1DECB8C9FE5BF8B2256F244 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 98763D00A1261E2C77540ECBDA0197F6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 9C2D21C8DF3376328FDEC9431B8B8DEB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + A0CA2737162685D26F3D72473DF55E16 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + A16D31BE4F883B9CA8546DDBE266BC2C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + AE8690FCA2E55E8CD7E79A02A8041A40 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + AFB753BAE2F4F5EBBD74FB3A18D2CD2E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + AFD7E3A2A6E9E918AA33CE4549DCB080 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + B26047A963065253F0D379249059EDF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + B725E1CDA4D0FBDE46907D3D1BD4DDC4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + BBDD0024DF8A3C8B835FFC73AEF9F5D6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + BC7CF60269466E79C607EF2A2D1EB2E6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + BD278C26B16F39574329F7F8395C8D9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + C336B15FD74D6A57E675FBEEF914F09B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CAD3534FC55B0333104E5117C0A9A324; + remoteInfo = GoogleSignIn; + }; + C5C8C97EA08D7637A211D3FCFC914B1A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + C6D8AA5C1C0D1DA09D9F3ED749DC5FD2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + C89B6FC29E6485480F8DE9C1C0F308FD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + CBC29057F9DA163AA37E9D817574A9D0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8627999EF1D5E93E13DAFF580DA8CDCF; + remoteInfo = GTMAppAuth; + }; + D284B0AC1AF1E545BB972919C4F5A1CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + D4360B33CFE1C713F022BA548944EBD1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C642AA10FB29936669CC269F42079C6; + remoteInfo = AppAuth; + }; + DD8C535932A07608FAAA02FC95FD2C3A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + E71226CA418EB410327E4AA7178A6FBB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6D45934038562DBC96227173D041A9C1; + remoteInfo = FirebaseUI; + }; + E77389552F5BAF3B750CBB3711CB5975 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + E981732EC7122F9C1BD1A4EE59406149 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 23E7C4A52360C026F97E4A96D91B03CE; + remoteInfo = FirebaseStorage; + }; + ED8943D69B5E68F0DF5139DE83ACDDDD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + F2F7AB46ED380C7679FD87C608E79235 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CAD3534FC55B0333104E5117C0A9A324; + remoteInfo = GoogleSignIn; + }; + F35AF7AB340D596F14D7D42CCAB7EBE9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + F91D960E25A246F641BB599B261122C9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + FFDCDD20625795143B0591AFFE295B52 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 23E7C4A52360C026F97E4A96D91B03CE; + remoteInfo = FirebaseStorage; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 405382FE2AA5F751FF32CABE0F41BE63 /* Copy . Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + 3E012F2BD62CA7B586A77595AE407C2B /* FBLPromise+All.h in Copy . Public Headers */, + 21C66A6702A435302E9A3BB27D0BCD14 /* FBLPromise+Always.h in Copy . Public Headers */, + 271CB6B0B9E91B2F550C0603B5543ADA /* FBLPromise+Any.h in Copy . Public Headers */, + 50F995B1B2C6D541C2A727889F65178B /* FBLPromise+Async.h in Copy . Public Headers */, + B0CCE74526E2B1199108FC568234C9C5 /* FBLPromise+Await.h in Copy . Public Headers */, + C93E85DCD5DFF7331EA4DC662B138FCB /* FBLPromise+Catch.h in Copy . Public Headers */, + 10D6FD725A3B8210C27EB011330862F7 /* FBLPromise+Delay.h in Copy . Public Headers */, + AF756AB48E3B3095C78B0AF82BD84FD6 /* FBLPromise+Do.h in Copy . Public Headers */, + F4CBF2654015FB6A55443D30DB7C37E8 /* FBLPromise+Race.h in Copy . Public Headers */, + EAFB49066FAAAFCCFB16E7FF666F1D21 /* FBLPromise+Recover.h in Copy . Public Headers */, + ADB322EAF3B8C2E6D2655B03D1A20120 /* FBLPromise+Reduce.h in Copy . Public Headers */, + 214C0087B11C35AAB34197A6B2A05FD6 /* FBLPromise+Retry.h in Copy . Public Headers */, + 389A5B099EF8432E317DE7FF3C0DAC13 /* FBLPromise+Testing.h in Copy . Public Headers */, + DAFA58E57C7E58B3C33229A7B383683A /* FBLPromise+Then.h in Copy . Public Headers */, + 4F2AE2ACC6468002D20E6F9FF150235A /* FBLPromise+Timeout.h in Copy . Public Headers */, + 348E1522ABB9E9CB80C3FC0F02EDAED0 /* FBLPromise+Validate.h in Copy . Public Headers */, + FD34718836DC0C3C9E44F282E8F9848B /* FBLPromise+Wrap.h in Copy . Public Headers */, + EDA75E998D1315C52E7CBD7E3D040555 /* FBLPromise.h in Copy . Public Headers */, + FE7FEF31EB3953731D45A601645FBB37 /* FBLPromiseError.h in Copy . Public Headers */, + 77ACB4CA3803992854F1A1B0DE0190A6 /* FBLPromises.h in Copy . Public Headers */, + ); + name = "Copy . Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; + A0C1BAEE747133B982DB482F7E4987EE /* Copy . Private Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PRIVATE_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + 0C35999BF6A9FBF3D42A76F1C4D3BDCD /* FBLPromisePrivate.h in Copy . Private Headers */, + ); + name = "Copy . Private Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 002837788CEDF728C9F8B00AE09AF35E /* vi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = vi.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/vi.lproj; sourceTree = ""; }; + 008F4820544BC65FA5681C6A4E10A41A /* OIDAuthorizationResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDAuthorizationResponse.m; path = Source/AppAuthCore/OIDAuthorizationResponse.m; sourceTree = ""; }; + 0098C77A2AF070A9DED76E3055458A8C /* ca.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ca.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ca.lproj; sourceTree = ""; }; + 00AC724E951A64118AD7189A15610DE6 /* FIRSignUpNewUserResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSignUpNewUserResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.m; sourceTree = ""; }; + 00DECA92B7EE6396FB998E278B411EB9 /* FIRTwitterAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTwitterAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.h; sourceTree = ""; }; + 00E9ACE5B742B168BBAD473E28C5130C /* PromisesObjC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PromisesObjC.debug.xcconfig; sourceTree = ""; }; + 00FF6D3534EC1D8A91F5F95AD021827C /* FIRActionCodeSettings.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRActionCodeSettings.m; path = FirebaseAuth/Sources/Auth/FIRActionCodeSettings.m; sourceTree = ""; }; + 01233744AC84606574A5754E9A96964E /* FClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FClock.h; path = Firebase/Database/FClock.h; sourceTree = ""; }; + 01319D0532FDE21A1DAB1F8E6E5716CE /* nl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = nl.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/nl.lproj; sourceTree = ""; }; + 01A4C1808C82E6CD358A94DB8090721E /* OIDClientMetadataParameters.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDClientMetadataParameters.m; path = Source/AppAuthCore/OIDClientMetadataParameters.m; sourceTree = ""; }; + 01B5588E52D3B11F82A0D7F0C8DDAF9F /* FOperationSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOperationSource.m; path = Firebase/Database/Core/Operation/FOperationSource.m; sourceTree = ""; }; + 01DB54993FD7E077C1A2FDA6680AD562 /* sk.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sk.lproj; path = Auth/FirebaseAuthUI/Strings/sk.lproj; sourceTree = ""; }; + 02A0E580086D035BB4EC4EFA878CAC1D /* FIRStorageGetMetadataTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetMetadataTask.h; path = FirebaseStorage/Sources/FIRStorageGetMetadataTask.h; sourceTree = ""; }; + 02B3AF231CF542962F689F76E52481E7 /* GDTCORLifecycle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORLifecycle.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m; sourceTree = ""; }; + 0318A5FEF1987622B3803E57493B9BD9 /* GoogleDataTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GoogleDataTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h; sourceTree = ""; }; + 031EB143A6EDC569B9AB682402960F1A /* merger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = merger.h; path = table/merger.h; sourceTree = ""; }; + 03239C2D092CAF3AABFEE00AF21A83AA /* en-IN.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-IN.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-IN.lproj"; sourceTree = ""; }; + 03299E70B14A8CA0CD3B288F7D43BE4A /* FUIAccountSettingsOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperation.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.m; sourceTree = ""; }; + 0353E7DD4FD4E16ACEFB53AC1DDFAC78 /* GULKeychainStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULKeychainStorage.m; path = GoogleUtilities/Environment/SecureStorage/GULKeychainStorage.m; sourceTree = ""; }; + 0390D03D2B6A00354D273E01C6ABA200 /* FirebaseUI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseUI-umbrella.h"; sourceTree = ""; }; + 03AC94CC3669CD2F4343DCD28A98153B /* de.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = de.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/de.lproj; sourceTree = ""; }; + 03B2F71602C9A737FACA970FCE8F7BD7 /* GDTCORConsoleLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORConsoleLogger.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m; sourceTree = ""; }; + 03C4883C10FF5038DF368CDEDE4218B7 /* ru.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ru.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ru.lproj; sourceTree = ""; }; + 03F04BE92A78E9CB93B09F492E85AAF1 /* bn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = bn.lproj; path = Auth/FirebaseAuthUI/Strings/bn.lproj; sourceTree = ""; }; + 044E68ADDD610FF0750545E3E8E7FEBB /* fil.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fil.lproj; path = Auth/FirebaseAuthUI/Strings/fil.lproj; sourceTree = ""; }; + 04B732645135CA8B3E7FA00F9C6EDB77 /* FWriteRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteRecord.h; path = Firebase/Database/Core/FWriteRecord.h; sourceTree = ""; }; + 04D93189E444EF105CE4F9D654BE2315 /* ta.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ta.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ta.lproj; sourceTree = ""; }; + 04FD97AE67C10679D659B68EFCB64697 /* de-AT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "de-AT.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/de-AT.lproj"; sourceTree = ""; }; + 052053BBDBFA807842AEFBCF43F360FB /* OIDAuthStateChangeDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthStateChangeDelegate.h; path = Source/AppAuthCore/OIDAuthStateChangeDelegate.h; sourceTree = ""; }; + 0534AAF51A65ACC6357CCDC6F5B9A17A /* pl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pl.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/pl.lproj; sourceTree = ""; }; + 0540204F58B685F054530616C561282B /* export.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = export.h; path = include/leveldb/export.h; sourceTree = ""; }; + 05767D0A7CDA76A6FB22D66FA268BFF6 /* FCompoundHash.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundHash.m; path = Firebase/Database/Core/FCompoundHash.m; sourceTree = ""; }; + 058B86FB42735EFF6012341A73CFD1FF /* FIRBundleUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRBundleUtil.m; path = FirebaseCore/Sources/FIRBundleUtil.m; sourceTree = ""; }; + 0594A0CB5786656C000F34DF38D7548E /* ic_visibility@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_visibility@2x.png"; path = "Auth/FirebaseAuthUI/Resources/ic_visibility@2x.png"; sourceTree = ""; }; + 05FBF2C6D14E46A75180F9E7C78B1A5E /* cs.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = cs.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/cs.lproj; sourceTree = ""; }; + 0676931B0B675CD8006C8315CEDA9D2D /* pt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pt.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/pt.lproj; sourceTree = ""; }; + 06AE775865E552A747572F5608D9863A /* GDTCORStorageProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStorageProtocol.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORStorageProtocol.h; sourceTree = ""; }; + 06E17AEBC3D9DCBAAA1DF718952385F8 /* OIDError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDError.m; path = Source/AppAuthCore/OIDError.m; sourceTree = ""; }; + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = nanopb.framework; path = nanopb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0735B2D4D87BB62774F7B9557FBF231F /* pt-BR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "pt-BR.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-BR.lproj"; sourceTree = ""; }; + 079E3CAFC7164BEDEA7B74133125300C /* FIRDataSnapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDataSnapshot.m; path = Firebase/Database/Api/FIRDataSnapshot.m; sourceTree = ""; }; + 07EFF1CBAC30ED458104AF65FAFE793E /* leveldb-library-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-umbrella.h"; sourceTree = ""; }; + 08441C78A0B36E7813F97FB64E0E9B1F /* FIRAuthWebView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthWebView.h; path = FirebaseAuth/Sources/Utilities/FIRAuthWebView.h; sourceTree = ""; }; + 085975BA993F8543295A94EECBDD6ECF /* FIRDatabaseQuery_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h; sourceTree = ""; }; + 0889F6ED1E26D93D3A5813350CCC106E /* GULSecureCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSecureCoding.m; path = GoogleUtilities/Environment/GULSecureCoding.m; sourceTree = ""; }; + 08E72A8C52BAD62FEB94490A1F2BF9B8 /* NSData+FIRBase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+FIRBase64.h"; path = "FirebaseAuth/Sources/Utilities/NSData+FIRBase64.h"; sourceTree = ""; }; + 0992AED4D85D10AED6036ECFCAAF7207 /* OIDAuthState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDAuthState.m; path = Source/AppAuthCore/OIDAuthState.m; sourceTree = ""; }; + 09A097B832C0A5236DD3C244CE58A25C /* FirebaseStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseStorage.h; path = FirebaseStorage/Sources/Public/FirebaseStorage.h; sourceTree = ""; }; + 09D08393443CCDD8CF77D6023BAAC3A4 /* FIRHeartbeatInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRHeartbeatInfo.m; path = FirebaseCore/Sources/FIRHeartbeatInfo.m; sourceTree = ""; }; + 0A6735AEC88EBDF9980427BEC3A16C7F /* testutil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testutil.h; path = util/testutil.h; sourceTree = ""; }; + 0A848E3033A143373574E05527F9066C /* Pods-MyExperiences-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-MyExperiences-resources.sh"; sourceTree = ""; }; + 0A854E381D55BE2A7E3E8AABADB04EBE /* FIRInstallationsIIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h; sourceTree = ""; }; + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = leveldb.framework; path = "leveldb-library.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AA3BC8FBC301E1AD271B8BC56131017 /* FIRAuthRPCRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthRPCRequest.h; path = FirebaseAuth/Sources/Backend/FIRAuthRPCRequest.h; sourceTree = ""; }; + 0AECB71732ABD8587D9BB4DE4FD97046 /* FIRTwitterAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRTwitterAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthCredential.m; sourceTree = ""; }; + 0B02D893464CD1AA4EC9495A6C0FBAB6 /* FIRStorageTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTask.h; path = FirebaseStorage/Sources/Public/FIRStorageTask.h; sourceTree = ""; }; + 0B2F5E8C7D0001EC52275D753C23D8D0 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + 0B7DE22D7576368040FBF615532A0DA3 /* GTMSessionFetcherService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcherService.h; path = Source/GTMSessionFetcherService.h; sourceTree = ""; }; + 0B82EF8025DA0FBD0188AD9F091FBB70 /* FCacheNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCacheNode.h; path = Firebase/Database/Core/View/FCacheNode.h; sourceTree = ""; }; + 0B94E6B8AF33C56D68D4AD9BAA5FEE2A /* FirebaseCore.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.debug.xcconfig; sourceTree = ""; }; + 0BA57690C4CA9DFE949ED25284DEB517 /* OIDAuthorizationRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDAuthorizationRequest.m; path = Source/AppAuthCore/OIDAuthorizationRequest.m; sourceTree = ""; }; + 0BE0652F32B8FA6E5D02FA260895209B /* es-US.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-US.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-US.lproj"; sourceTree = ""; }; + 0BEA2C64BB6137F4C8D76D2555CD2590 /* OIDExternalUserAgentIOS.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentIOS.h; path = Source/AppAuth/iOS/OIDExternalUserAgentIOS.h; sourceTree = ""; }; + 0BEBBED032A65D6D7E7177E7EBD6307E /* FIRDeleteAccountResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDeleteAccountResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.h; sourceTree = ""; }; + 0BEF95068A2B04D39985E4D2821BDE9E /* FIRSecureTokenRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSecureTokenRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.m; sourceTree = ""; }; + 0BF58E7BD20A582ADA2FE78D5B00B44D /* slice.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = slice.h; path = include/leveldb/slice.h; sourceTree = ""; }; + 0C06F2CB64F40C1BEFC844D191BCED3C /* FIRFacebookAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFacebookAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.h; sourceTree = ""; }; + 0C0B61C5273C700F880D6781D3AF1920 /* FirebaseCoreDiagnostics.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnostics.debug.xcconfig; sourceTree = ""; }; + 0C29E6056C2E52C3272F5DBF03A284B7 /* comparator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = comparator.cc; path = util/comparator.cc; sourceTree = ""; }; + 0C6ED211312B3541D9CED14186669579 /* gu.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = gu.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/gu.lproj; sourceTree = ""; }; + 0C79891D26C39DACEE62796D724DBFCE /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + 0C8A0A0BC4CDBE2A71CCF4AF70BABC39 /* FTupleObjects.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjects.h; path = Firebase/Database/Utilities/Tuples/FTupleObjects.h; sourceTree = ""; }; + 0C9657B10159A1EF60ADA1CA1B6C1E71 /* FIndexedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedNode.h; path = Firebase/Database/Snapshot/FIndexedNode.h; sourceTree = ""; }; + 0CBCAC752D4D966314C7ED6C79EF83E9 /* FIRGitHubAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGitHubAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRGitHubAuthProvider.h; sourceTree = ""; }; + 0D7E8EFB9E99E8AAFEA96ACA4086DBE3 /* FTupleTSN.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTSN.h; path = Firebase/Database/Utilities/Tuples/FTupleTSN.h; sourceTree = ""; }; + 0DF00E0B4050F287AF4F7EF1D9D3520D /* tr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = tr.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/tr.lproj; sourceTree = ""; }; + 0E2FDE1552CDE29E8BEE17FA5D661B3B /* zh-Hans.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hans.lproj"; path = "Auth/FirebaseAuthUI/Strings/zh-Hans.lproj"; sourceTree = ""; }; + 0E7D49DB2F3223117BA44B91C6B9E48A /* FIRVerifyPasswordRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyPasswordRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.m; sourceTree = ""; }; + 0F25C53B0BE44DB7561861818BF846CF /* version_edit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_edit.h; path = db/version_edit.h; sourceTree = ""; }; + 0F53635464E43DABB555A566F5EE35DB /* fr-CH.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "fr-CH.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/fr-CH.lproj"; sourceTree = ""; }; + 0F948F6E03F0241D6A276C287317A33B /* FirebaseAuth.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAuth.debug.xcconfig; sourceTree = ""; }; + 0FA4D3EEB0242AE4F3CCF1D1B12BB2D5 /* FIRInstallationsStoredItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredItem.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m; sourceTree = ""; }; + 0FA4EB3669CA064C1FDF3FDF3E4098E6 /* OIDIDToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDIDToken.m; path = Source/AppAuthCore/OIDIDToken.m; sourceTree = ""; }; + 0FB4B2E3214664E3EC1748DB3C76B35B /* FIRVerifyPhoneNumberRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyPhoneNumberRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.h; sourceTree = ""; }; + 0FCE96FB03C7E2B07F0D846224B8050B /* FIRGitHubAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGitHubAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.h; sourceTree = ""; }; + 0FE79FE50D4F48F8C58CB949DBE4AC0D /* FUIAccountSettingsOperationDeleteAccount.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationDeleteAccount.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.h; sourceTree = ""; }; + 10414BB146383FB69BFD1324CB140BD4 /* FTupleOnDisconnect.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleOnDisconnect.m; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m; sourceTree = ""; }; + 104E98D4E5F9FA4F8720F910348707B0 /* FTrackedQueryManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQueryManager.h; path = Firebase/Database/Persistence/FTrackedQueryManager.h; sourceTree = ""; }; + 105D55B1653C85994022CD7D23E05D05 /* FIRVerifyPhoneNumberRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyPhoneNumberRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberRequest.m; sourceTree = ""; }; + 1072480B6864673EECB3B1CB257C0283 /* FirebaseInstallations-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstallations-dummy.m"; sourceTree = ""; }; + 109D4BE629EBB055BB466DE4AF91C32E /* GoogleDataTransportCCTSupport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransportCCTSupport.modulemap; sourceTree = ""; }; + 10A31E89F0E82B96B1774125C4430CCF /* nb.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = nb.lproj; path = Auth/FirebaseAuthUI/Strings/nb.lproj; sourceTree = ""; }; + 10C804434EE90A3648EAC6407DCF9D28 /* FTupleObjectNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjectNode.m; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.m; sourceTree = ""; }; + 10CEE0353BF9A5552A076306DA76AEE7 /* FBLPromise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromise.h; path = Sources/FBLPromises/include/FBLPromise.h; sourceTree = ""; }; + 10E687CA6920D53CFA44E0E9B9ED3E2A /* FBLPromise+Catch.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Catch.m"; path = "Sources/FBLPromises/FBLPromise+Catch.m"; sourceTree = ""; }; + 110B6B1D764C872D7748B1386AF6E5D0 /* GDTCORUploadPackage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadPackage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m; sourceTree = ""; }; + 113E302B441B981A827DD3B4EF35419F /* FTupleCallbackStatus.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleCallbackStatus.m; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m; sourceTree = ""; }; + 118374FE49AD27D512B8BA9E44E4B3EB /* FViewProcessorResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessorResult.h; path = Firebase/Database/FViewProcessorResult.h; sourceTree = ""; }; + 11C637F7FD1011CD32D6B2CF1B22A474 /* GULLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULLogger.m; path = GoogleUtilities/Logger/GULLogger.m; sourceTree = ""; }; + 12687F38DDA65406B56C297FA9B2EE9B /* APLevelDB.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = APLevelDB.h; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h"; sourceTree = ""; }; + 1298FE36D6175255C29C7661A7C10629 /* GTMOAuth2KeychainCompatibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMOAuth2KeychainCompatibility.m; path = Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.m; sourceTree = ""; }; + 12A895F05CE634F89A21DA41783A9423 /* dumpfile.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dumpfile.cc; path = db/dumpfile.cc; sourceTree = ""; }; + 12AA880F6A063BFB19894928A16F070A /* GoogleDataTransport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransport.release.xcconfig; sourceTree = ""; }; + 12F9164B27690D519BFFCC086D81CFFD /* FIRTwitterAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRTwitterAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/Twitter/FIRTwitterAuthProvider.m; sourceTree = ""; }; + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstallations.framework; path = FirebaseInstallations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 13D66A61C6F8FE04AD5A3BADADA1656D /* FIRStorageReference.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageReference.m; path = FirebaseStorage/Sources/FIRStorageReference.m; sourceTree = ""; }; + 13E8EE1DCB09BF77593099C551FC273C /* FIRInstallationsLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsLogger.m; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.m; sourceTree = ""; }; + 1405A82BE0B36A65A6E5B9FA9BBECE56 /* FRangeMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangeMerge.h; path = Firebase/Database/Core/FRangeMerge.h; sourceTree = ""; }; + 144230DCCAA8A18DA6384E2CBB093FFC /* FIRNoopAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRNoopAuthTokenProvider.h; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.h; sourceTree = ""; }; + 147ABC58AAD1BAF83AAFFD3ED20DF9CB /* FIRAuthTokenResult_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthTokenResult_Internal.h; path = FirebaseAuth/Sources/Auth/FIRAuthTokenResult_Internal.h; sourceTree = ""; }; + 14FE6A4FB9D07E0668CC728919204386 /* NSData+FIRBase64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+FIRBase64.m"; path = "FirebaseAuth/Sources/Utilities/NSData+FIRBase64.m"; sourceTree = ""; }; + 155468BB75CD9DCF1B69D9F7A0A9355D /* OIDError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDError.h; path = Source/AppAuthCore/OIDError.h; sourceTree = ""; }; + 1564C41BABD3DE7AA9CA05FEC60DFFD6 /* FIRStorageUploadTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUploadTask_Private.h; path = FirebaseStorage/Sources/FIRStorageUploadTask_Private.h; sourceTree = ""; }; + 156A0CE6C28B38095AF9138DBEE5A713 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProtoFinalizeMFAPhoneResponseInfo.m; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.m; sourceTree = ""; }; + 156E36CC1801474606A0B980E1DF1182 /* OIDResponseTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDResponseTypes.h; path = Source/AppAuthCore/OIDResponseTypes.h; sourceTree = ""; }; + 15C962C270CF2E0D68ACC36DDF996B77 /* FChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChange.m; path = Firebase/Database/Core/View/FChange.m; sourceTree = ""; }; + 15CBA6967F032A28843A65A901C56F28 /* FIRStartMFASignInResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStartMFASignInResponse.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.h; sourceTree = ""; }; + 15EDF646C56C65236F9F00B1FAF8A64D /* FIRGetOOBConfirmationCodeRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetOOBConfirmationCodeRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.m; sourceTree = ""; }; + 15F815C512EA7B4CD9D9AB719AABC2DF /* GoogleUtilities.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.release.xcconfig; sourceTree = ""; }; + 160F9D533A4A53571BA6D1E2172D1F0C /* gsw.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = gsw.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/gsw.lproj; sourceTree = ""; }; + 16222C91E613CBB3BA3B1594E89FD7D7 /* es-PA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PA.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PA.lproj"; sourceTree = ""; }; + 16296FC7FAD4F7911C51F68AFD78E15F /* fr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fr.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/fr.lproj; sourceTree = ""; }; + 163D0E58B78F8F26B3921C24D10FE991 /* ur.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ur.lproj; path = Auth/FirebaseAuthUI/Strings/ur.lproj; sourceTree = ""; }; + 169EC26D74379B8E784D2BAD7F05FBAA /* FBLPromise+Recover.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Recover.h"; path = "Sources/FBLPromises/include/FBLPromise+Recover.h"; sourceTree = ""; }; + 16A005FC0FE4E4802BA3D80F616EDBE2 /* FirebaseCoreDiagnostics.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnostics.release.xcconfig; sourceTree = ""; }; + 16AF194D65A9EDA527517C4CBA700597 /* OIDRegistrationRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDRegistrationRequest.h; path = Source/AppAuthCore/OIDRegistrationRequest.h; sourceTree = ""; }; + 16B53E64756CED682CA2F191367C5A91 /* OIDAuthState+IOS.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OIDAuthState+IOS.h"; path = "Source/AppAuth/iOS/OIDAuthState+IOS.h"; sourceTree = ""; }; + 17A216C406500454DF05929B98E58410 /* ic_google@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_google@2x.png"; path = "GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@2x.png"; sourceTree = ""; }; + 17D499F429E7B17807816EF3C2257723 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 180AD6EE5C9A774D35CCC09E2C3643B3 /* FTrackedQueryManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQueryManager.m; path = Firebase/Database/Persistence/FTrackedQueryManager.m; sourceTree = ""; }; + 180C6EA8C3894CB86B604C1AAA40521F /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + 187318BA2B8C87BF94F4551700E3363D /* lv.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = lv.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/lv.lproj; sourceTree = ""; }; + 187E5952DB3FBDBC83676A1C55427733 /* FIRSignUpNewUserRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSignUpNewUserRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h; sourceTree = ""; }; + 1888721E3588FD46C7845A8A58070079 /* FTreeSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h; sourceTree = ""; }; + 18A7C0C0F3FDF3AEAF2C3758A25AFD61 /* FIRApp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRApp.h; path = FirebaseCore/Sources/Public/FIRApp.h; sourceTree = ""; }; + 18B8C3ED9FC01D4F3116710E7ADBBBEA /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + 18E84252C8BBFC1F7C570CCCEA4B789D /* FUIAccountSettingsViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsViewController.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.m; sourceTree = ""; }; + 18FDC64B1FC85B24ABB1C0364C15D919 /* FTupleObjects.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjects.m; path = Firebase/Database/Utilities/Tuples/FTupleObjects.m; sourceTree = ""; }; + 190DF118BCA465ED356FCBBE1176A561 /* ro.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ro.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ro.lproj; sourceTree = ""; }; + 19DF54507D0D63DE4425E3FE350B9832 /* FIRVerifyPhoneNumberResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyPhoneNumberResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.h; sourceTree = ""; }; + 1A2746E30564EC71904AB662184CD169 /* es-419.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-419.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-419.lproj"; sourceTree = ""; }; + 1A62BB8032FBA738F4F2D57C13670651 /* cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cache.h; path = include/leveldb/cache.h; sourceTree = ""; }; + 1A65101F6630AA9877B2525A96442662 /* FIRAuth.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuth.m; path = FirebaseAuth/Sources/Auth/FIRAuth.m; sourceTree = ""; }; + 1A7A8CD6C8BB3A13F9B114C37E9FEAC4 /* gsw.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = gsw.lproj; path = Auth/FirebaseAuthUI/Strings/gsw.lproj; sourceTree = ""; }; + 1A8D7D0BBB9B7971147224F4CC49B258 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + 1AC5C1368897ED0DB6D31746B4B0ACC8 /* FUIAuthErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthErrors.h; path = Auth/FirebaseAuthUI/FUIAuthErrors.h; sourceTree = ""; }; + 1AF78B774DA999F5D69F23DCEDDC29DF /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + 1B2164BDA4D418A43841726EE9530F9B /* table_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_builder.cc; path = table/table_builder.cc; sourceTree = ""; }; + 1B49E6C76268B31F8E5AB9787C649111 /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + 1B646542193B39A1752CBECC2CFB5F39 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + 1B69E273AC1F848FB9E6B3E2592B78DF /* FTreeNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeNode.m; path = Firebase/Database/Core/Utilities/FTreeNode.m; sourceTree = ""; }; + 1B851A17E68A633AC605EF3F4D6C2A38 /* FIRErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRErrors.m; path = FirebaseCore/Sources/FIRErrors.m; sourceTree = ""; }; + 1B85E94CC4133DE93C8AB2185EB576E2 /* FIRStorageConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageConstants.h; path = FirebaseStorage/Sources/Public/FIRStorageConstants.h; sourceTree = ""; }; + 1C02CBFECE78F11F07A8DC5E7561F36C /* FirebaseCoreInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCoreInternal.h; path = FirebaseCore/Sources/Private/FirebaseCoreInternal.h; sourceTree = ""; }; + 1C3CA4F92C08777AF6CB0CC107100639 /* arena.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = arena.h; path = util/arena.h; sourceTree = ""; }; + 1C7959E841ED9CAC4E3DFABCC07D4C93 /* FBLPromiseError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromiseError.h; path = Sources/FBLPromises/include/FBLPromiseError.h; sourceTree = ""; }; + 1C9F8DDC9502A6EE00DABC661FA82ABA /* FIRInstallations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallations.m; path = FirebaseInstallations/Source/Library/FIRInstallations.m; sourceTree = ""; }; + 1CC0A3191504AAE5AC701D8DDF35DB9A /* FValidation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValidation.m; path = Firebase/Database/Utilities/FValidation.m; sourceTree = ""; }; + 1CD458A32FF2A6B04A8196DCD333D719 /* es-CO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CO.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CO.lproj"; sourceTree = ""; }; + 1CE5CAD485E3BB64ADEA5F812EAD1AFF /* FIRStorageListTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageListTask.m; path = FirebaseStorage/Sources/FIRStorageListTask.m; sourceTree = ""; }; + 1D3F00A4E6D8568D60392BAC86AE8673 /* FIRPhoneMultiFactorGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRPhoneMultiFactorGenerator.m; path = FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorGenerator.m; sourceTree = ""; }; + 1D5504A5FE446BDC72CA754CF944A4C9 /* GoogleAppMeasurement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleAppMeasurement.framework; path = Frameworks/GoogleAppMeasurement.framework; sourceTree = ""; }; + 1D873F482DABA5FEA5DF77519B4A35C6 /* OIDEndSessionRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDEndSessionRequest.h; path = Source/AppAuthCore/OIDEndSessionRequest.h; sourceTree = ""; }; + 1D8CC6D3E8DCFA0BC10D29F0D214F685 /* FCancelEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCancelEvent.m; path = Firebase/Database/Core/View/FCancelEvent.m; sourceTree = ""; }; + 1DC7679A2F6487DA883CD86CD58DD9FE /* FBLPromise+Wrap.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Wrap.m"; path = "Sources/FBLPromises/FBLPromise+Wrap.m"; sourceTree = ""; }; + 1E003F27645520032E3624A30B1B9E93 /* FIRLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRLogger.m; path = FirebaseCore/Sources/FIRLogger.m; sourceTree = ""; }; + 1E9E8BC8EA3AD45E32FC2E6FD0DFAADB /* FCompoundWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundWrite.h; path = Firebase/Database/Snapshot/FCompoundWrite.h; sourceTree = ""; }; + 1EF65A483BB4A3FD7205F21724439323 /* de-CH.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "de-CH.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/de-CH.lproj"; sourceTree = ""; }; + 1F0FD4060063C5168EA8438027D27297 /* FIRAuthSerialTaskQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthSerialTaskQueue.m; path = FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.m; sourceTree = ""; }; + 1F2114000F4B4E452E61D687C2422EB2 /* FIRMultiFactorAssertion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMultiFactorAssertion.h; path = FirebaseAuth/Sources/Public/FIRMultiFactorAssertion.h; sourceTree = ""; }; + 1F7AF946105D40415BEE2B4C29262A5D /* GULNetworkMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkMessageCode.h; path = GoogleUtilities/Network/Private/GULNetworkMessageCode.h; sourceTree = ""; }; + 1F7DC439F0D2B26FCAA3BB600B86D9A7 /* lv.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = lv.lproj; path = Auth/FirebaseAuthUI/Strings/lv.lproj; sourceTree = ""; }; + 1FDCB2F5383C1A7C7A91F0F135CAC071 /* FIRAuthAppCredentialManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthAppCredentialManager.h; path = FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.h; sourceTree = ""; }; + 1FE785EE6344006DCC6CCF1EB97E4675 /* FIndexedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedFilter.m; path = Firebase/Database/Core/View/Filter/FIndexedFilter.m; sourceTree = ""; }; + 20070732AC1D13563706D375942B5198 /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + 207EDF36E35871F4F9C7108E522E144F /* FRepoInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoInfo.h; path = Firebase/Database/Core/FRepoInfo.h; sourceTree = ""; }; + 20BC6706A3B2DCD001B2917F79F8F31F /* FIRStartMFAEnrollmentResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStartMFAEnrollmentResponse.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.m; sourceTree = ""; }; + 20E3C25D260E7FAD721012E746F5ECD9 /* gu.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = gu.lproj; path = Auth/FirebaseAuthUI/Strings/gu.lproj; sourceTree = ""; }; + 20EABA71D9A42FBE54F15ED4D7A36D2C /* nn-NO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "nn-NO.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/nn-NO.lproj"; sourceTree = ""; }; + 213BBD3DBEF0184BBDFCEB20FF14F4EE /* FLevelDBStorageEngine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLevelDBStorageEngine.m; path = Firebase/Database/Persistence/FLevelDBStorageEngine.m; sourceTree = ""; }; + 214BBB5E706185291198C7A134E4DB40 /* leveldb-library-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "leveldb-library-Info.plist"; sourceTree = ""; }; + 218384F9184D07D0CC75E9E2D849833E /* FIRStorageGetDownloadURLTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetDownloadURLTask_Private.h; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h; sourceTree = ""; }; + 218CAE055A0262CE3E2519316FDB660B /* FirebaseAuthVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FirebaseAuthVersion.m; path = FirebaseAuth/Sources/FirebaseAuthVersion.m; sourceTree = ""; }; + 21BF9FC4620C4B9524CE633385AE1764 /* FIRTransactionResult_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult_Private.h; path = Firebase/Database/Api/Private/FIRTransactionResult_Private.h; sourceTree = ""; }; + 21E390ED7946A6255192CC662B974485 /* FIRAuthWebViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthWebViewController.m; path = FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.m; sourceTree = ""; }; + 234F4C1B718C50970467A34598D11AEF /* FUIAuthBaseViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthBaseViewController.h; path = Auth/FirebaseAuthUI/FUIAuthBaseViewController.h; sourceTree = ""; }; + 23C82953FC80B9C61F784D4B27E54E19 /* es-CL.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CL.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CL.lproj"; sourceTree = ""; }; + 23D196E2657D5CF6B7EEEA795134088B /* es-VE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-VE.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-VE.lproj"; sourceTree = ""; }; + 23EBD84FD0800C9B1C349C22E48EEDFA /* GTMAppAuth.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GTMAppAuth.modulemap; sourceTree = ""; }; + 24191B50B213697BDB0A03CD396569F7 /* FTupleNodePath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleNodePath.h; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.h; sourceTree = ""; }; + 249F2A82CBC0749A828D61764B441E28 /* AppAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 24A357EADAA35A7EF0EA56AA88103251 /* GULReachabilityMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityMessageCode.h; path = GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h; sourceTree = ""; }; + 24A6A8B562A7BB27357C8B086C0E3880 /* FIREmailLinkSignInResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIREmailLinkSignInResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.h; sourceTree = ""; }; + 24C2DE86CB1BC54A75C3E5D22F13585F /* options.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = options.h; path = include/leveldb/options.h; sourceTree = ""; }; + 24C633FD22C7C3FC566586ADA13E5100 /* GoogleAppMeasurement.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.release.xcconfig; sourceTree = ""; }; + 24C6B81A862144EBBB10A29A617297D3 /* FTupleUserCallback.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleUserCallback.h; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.h; sourceTree = ""; }; + 24FE7022564CEAD1E6D3E5E23E421FC5 /* FSyncTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncTree.h; path = Firebase/Database/Core/FSyncTree.h; sourceTree = ""; }; + 2506B650F36439620CF54F5655EBDEDA /* es-CO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CO.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-CO.lproj"; sourceTree = ""; }; + 253FA02F3380D6F05F561C4A97AC5623 /* write_batch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch.h; path = include/leveldb/write_batch.h; sourceTree = ""; }; + 25585B514F999F152B161BDD883EF1FC /* FIRStartMFAEnrollmentResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStartMFAEnrollmentResponse.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentResponse.h; sourceTree = ""; }; + 25BCAC05D5A21C8998618E7016194613 /* FEventRaiser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventRaiser.m; path = Firebase/Database/Core/View/FEventRaiser.m; sourceTree = ""; }; + 25BE0E179757406561E2975B3099D56C /* Pods_MyExperiences.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_MyExperiences.framework; path = "Pods-MyExperiences.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 25BF8489D43A221CCEECB7FB5BAB2A7B /* FIRAuthWebView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthWebView.m; path = FirebaseAuth/Sources/Utilities/FIRAuthWebView.m; sourceTree = ""; }; + 25E645CD0A247B7C65BC6B8E58799DDC /* PromisesObjC-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PromisesObjC-dummy.m"; sourceTree = ""; }; + 25FDFB1572CA5FEEFA8354414A37A218 /* GULUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULUserDefaults.m; path = GoogleUtilities/UserDefaults/GULUserDefaults.m; sourceTree = ""; }; + 261D24E6A7E8FE448A9D6BBDBEAE06D4 /* OIDGrantTypes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDGrantTypes.h; path = Source/AppAuthCore/OIDGrantTypes.h; sourceTree = ""; }; + 2639674FFC61B91B6BC5DF9392EBF3DD /* FRepoManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoManager.h; path = Firebase/Database/Core/FRepoManager.h; sourceTree = ""; }; + 26A701B9267F7E760B27DF5EFD4E534A /* FParsedUrl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FParsedUrl.m; path = Firebase/Database/Utilities/FParsedUrl.m; sourceTree = ""; }; + 26AE83E15A11B203C7FC6321AEBFA6DD /* GoogleDataTransport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransport-Info.plist"; sourceTree = ""; }; + 26CCE65941065E0C84C417825219AFB5 /* GDTCORRegistrar_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h; sourceTree = ""; }; + 26EB1333BCF8E07CE70BEC92753A775C /* FUIPrivacyAndTermsOfServiceView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIPrivacyAndTermsOfServiceView.m; path = Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.m; sourceTree = ""; }; + 26FF61F5D948E7FB9711D97EEA148219 /* es-BO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-BO.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-BO.lproj"; sourceTree = ""; }; + 2707F538B792760E9D23053698344742 /* FIRStorageListResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageListResult.m; path = FirebaseStorage/Sources/FIRStorageListResult.m; sourceTree = ""; }; + 27556724AA71C3E4CA6F469D53BF1EEE /* env_windows_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_windows_test_helper.h; path = util/env_windows_test_helper.h; sourceTree = ""; }; + 275B5FDAECAB2575C5E82DA5E44D88CD /* FIRVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVersion.m; path = FirebaseCore/Sources/FIRVersion.m; sourceTree = ""; }; + 278BB3E5433817C52237810200BD9406 /* FIRStorageReference_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageReference_Private.h; path = FirebaseStorage/Sources/FIRStorageReference_Private.h; sourceTree = ""; }; + 279B1FA79AC353861C5CF0F52B5147CA /* FIRFinalizeMFAEnrollmentRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFinalizeMFAEnrollmentRequest.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.m; sourceTree = ""; }; + 27C158781A825E2584EA79FBE472E11B /* PromisesObjC-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PromisesObjC-umbrella.h"; sourceTree = ""; }; + 27D4D33D864D9FCB96217A3F5BE9F5D4 /* fa.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fa.lproj; path = Auth/FirebaseAuthUI/Strings/fa.lproj; sourceTree = ""; }; + 27F625BC0D3779D8A1792FFCD42550E0 /* FIRInstallationsVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsVersion.m; path = FirebaseInstallations/Source/Library/FIRInstallationsVersion.m; sourceTree = ""; }; + 280EEC179686C8D6A48F523385E2A95E /* GDTCORRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h; sourceTree = ""; }; + 2891BDA51C2AF6BC9404F4A7B1727870 /* FIRInstallationsStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStore.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h; sourceTree = ""; }; + 2898C5A20C3702B07918D03F9FBB0C3C /* builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = builder.h; path = db/builder.h; sourceTree = ""; }; + 294612EF265084E263D9B8EF81CEF4FC /* FRepo_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo_Private.h; path = Firebase/Database/Core/FRepo_Private.h; sourceTree = ""; }; + 2952573EE05F206F04E91F8CE6DBE770 /* FStringUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStringUtilities.h; path = Firebase/Database/Utilities/FStringUtilities.h; sourceTree = ""; }; + 295D5C63FA45919B29F2B47126BA3657 /* FIRVerifyCustomTokenResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyCustomTokenResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.h; sourceTree = ""; }; + 29D5A4375D1E8A2A55723BFF02AA7005 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProtoFinalizeMFAPhoneRequestInfo.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.h; sourceTree = ""; }; + 2A5EFA30C44EF4FB68F3C3D45A179EC3 /* FIRAuthSettings.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthSettings.m; path = FirebaseAuth/Sources/Auth/FIRAuthSettings.m; sourceTree = ""; }; + 2A7DC61A346E675EE6ABAE77C84599E6 /* FUIPrivacyAndTermsOfServiceView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIPrivacyAndTermsOfServiceView.h; path = Auth/FirebaseAuthUI/FUIPrivacyAndTermsOfServiceView.h; sourceTree = ""; }; + 2AA9752886E774984AD2D35449B849E7 /* FOverwrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOverwrite.h; path = Firebase/Database/Core/Operation/FOverwrite.h; sourceTree = ""; }; + 2ABB4EE4E5ED740CFBB582C2BB9B50DE /* FIRAuthAPNSToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthAPNSToken.h; path = FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.h; sourceTree = ""; }; + 2AD6E35DDB2EE9EE7ABB6F3C84BC29B5 /* GDTCCTNanopbHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTNanopbHelpers.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h; sourceTree = ""; }; + 2ADF4BE0B984457784EB53A44B4AE301 /* FLeafNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLeafNode.h; path = Firebase/Database/Snapshot/FLeafNode.h; sourceTree = ""; }; + 2AFED164F46BA096C4E58DA488DF0248 /* nn-NO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "nn-NO.lproj"; path = "Auth/FirebaseAuthUI/Strings/nn-NO.lproj"; sourceTree = ""; }; + 2B2E268A97351C2CC543523DFDCB9F94 /* FIRInstallationsVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsVersion.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h; sourceTree = ""; }; + 2B8DBE56121715EE74A27E96DF805741 /* GTMAppAuthFetcherAuthorization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMAppAuthFetcherAuthorization.m; path = Source/GTMAppAuthFetcherAuthorization.m; sourceTree = ""; }; + 2BA69B89E7BA669D98FB1669F1953521 /* GoogleDataTransport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransport.debug.xcconfig; sourceTree = ""; }; + 2BED935E00DCA51EE1CBD631ED2DE24E /* FIRStorageMetadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageMetadata.m; path = FirebaseStorage/Sources/FIRStorageMetadata.m; sourceTree = ""; }; + 2BFCFAAC8BFE82A214A763FFC468F8C1 /* GDTCORLifecycle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORLifecycle.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h; sourceTree = ""; }; + 2C08645CF610E0A55FA7C8135E3E4B04 /* FIRFinalizeMFASignInResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFinalizeMFASignInResponse.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.m; sourceTree = ""; }; + 2C32CD26CE098C26904AAD088DBBA4C6 /* FIRDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDiagnosticsData.h; path = FirebaseCore/Sources/FIRDiagnosticsData.h; sourceTree = ""; }; + 2C7B84BCD12457E28D8C0A6D55563C32 /* FTupleTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTransaction.h; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.h; sourceTree = ""; }; + 2C90A57F312058F5070F24619DF2D4AC /* FOverwrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOverwrite.m; path = Firebase/Database/Core/Operation/FOverwrite.m; sourceTree = ""; }; + 2CA5B41F52E3B66856135E15CC4759A8 /* FPersistentConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistentConnection.m; path = Firebase/Database/Core/FPersistentConnection.m; sourceTree = ""; }; + 2CC6A8024E61AF153A776058F0093984 /* FIROAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROAuthProvider.h; path = FirebaseAuth/Sources/Public/FIROAuthProvider.h; sourceTree = ""; }; + 2CEEFBDAF3FAAECFB109E6E0B60D19DB /* FIRInstallationsAuthTokenResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAuthTokenResult.m; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m; sourceTree = ""; }; + 2D00A435DFB725951078FD373898E52A /* pb_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_encode.h; sourceTree = ""; }; + 2D2A0CFFCC140A4E6C194F8D0FC5D628 /* FIRAuthGlobalWorkQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthGlobalWorkQueue.m; path = FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.m; sourceTree = ""; }; + 2D2DDAE0A59EACE0F9CF5B3655B713FB /* FBLPromise+All.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+All.h"; path = "Sources/FBLPromises/include/FBLPromise+All.h"; sourceTree = ""; }; + 2D67FC5FEB279446C5CFB3287D38A9DD /* FConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConnection.h; path = Firebase/Database/Realtime/FConnection.h; sourceTree = ""; }; + 2DB63E002E064E3C55D0852F18F0139B /* FCacheNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCacheNode.m; path = Firebase/Database/Core/View/FCacheNode.m; sourceTree = ""; }; + 2EBC0578E0831E699FDC8C670820885A /* FWebSocketConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWebSocketConnection.m; path = Firebase/Database/Realtime/FWebSocketConnection.m; sourceTree = ""; }; + 2F122A33B14CBFBDCBB14223CE8EDD41 /* FPathIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPathIndex.m; path = Firebase/Database/FPathIndex.m; sourceTree = ""; }; + 2F2239DC0B4B631FF8BCEFB670B66FD4 /* GDTCCTPrioritizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTPrioritizer.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m; sourceTree = ""; }; + 2F3F1CA3592AD79DF78A58DD1CCFBBAF /* FChildEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildEventRegistration.h; path = Firebase/Database/Core/View/FChildEventRegistration.h; sourceTree = ""; }; + 2F6BF72CB8650A8FFE6D0E969D4AF6B9 /* FUIStaticContentTableViewManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIStaticContentTableViewManager.m; path = Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.m; sourceTree = ""; }; + 2FA08E7E33E3A732A355057DBAD35E45 /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + 2FAB6110EBCEF5EFD9AAF97FB1E323CD /* GTMAppAuthFetcherAuthorization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMAppAuthFetcherAuthorization.h; path = Source/GTMAppAuthFetcherAuthorization.h; sourceTree = ""; }; + 2FDF1C00DD35EAEB9F29A29E8E1AEED7 /* FIRMultiFactorConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactorConstants.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactorConstants.m; sourceTree = ""; }; + 2FFBB31D3B28EE6DC5C2DAAF84FEA52A /* nanopb-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-prefix.pch"; sourceTree = ""; }; + 3002482FBBE4FC29A381308810AAFA04 /* FIRAuthDefaultUIDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthDefaultUIDelegate.h; path = FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.h; sourceTree = ""; }; + 303AEFF4641C47112E439DB5513D8778 /* GDTCORUploadCoordinator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadCoordinator.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m; sourceTree = ""; }; + 30554C35CED21FD072A6C0539122D9CD /* FIRAuthExceptionUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthExceptionUtils.m; path = FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.m; sourceTree = ""; }; + 3082E6493AB93A9C2593DFF6F5506755 /* pb_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_encode.c; sourceTree = ""; }; + 3097FE693219B2669E5404BF817BDBB3 /* FBLPromises.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FBLPromises.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 30CA6D91A8DDF03C7513D55329FD774C /* status.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = status.cc; path = util/status.cc; sourceTree = ""; }; + 310A0ABEA5C28EC185CCC6BE875BBC07 /* ic_visibility.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_visibility.png; path = Auth/FirebaseAuthUI/Resources/ic_visibility.png; sourceTree = ""; }; + 31403F1670FC70281DB296638EBBA5C0 /* FirebaseAuthVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseAuthVersion.h; path = FirebaseAuth/Sources/Public/FirebaseAuthVersion.h; sourceTree = ""; }; + 3196AD45943E4CD873BAA17255DC4131 /* fi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fi.lproj; path = Auth/FirebaseAuthUI/Strings/fi.lproj; sourceTree = ""; }; + 31C485AEEEEE2964C83DDD0480C6592E /* FIRSecureTokenService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSecureTokenService.m; path = FirebaseAuth/Sources/SystemService/FIRSecureTokenService.m; sourceTree = ""; }; + 31D97EF3B9821B7290206D1CC3E1440B /* FUIAuthBaseViewController_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthBaseViewController_Internal.h; path = Auth/FirebaseAuthUI/FUIAuthBaseViewController_Internal.h; sourceTree = ""; }; + 31F0F6B3F5A086DD87C96BDCFA6D3070 /* GULNetworkURLSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkURLSession.h; path = GoogleUtilities/Network/Private/GULNetworkURLSession.h; sourceTree = ""; }; + 31F1C186A4EAC68717CA9A6D6AE22852 /* FIRDatabaseConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig.h; path = Firebase/Database/Api/FIRDatabaseConfig.h; sourceTree = ""; }; + 31FEC4E1D3426CA59F02F81AF0A49EC6 /* FIREmailPasswordAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIREmailPasswordAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.h; sourceTree = ""; }; + 3206E36B58AC84FF7A082C1E27882B90 /* FIRDiagnosticsData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDiagnosticsData.m; path = FirebaseCore/Sources/FIRDiagnosticsData.m; sourceTree = ""; }; + 3225C5DFD5EEFAA06E0C3E77905A56EB /* FIRVerifyCustomTokenRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyCustomTokenRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.m; sourceTree = ""; }; + 32286A49973172FDDFAAEF75ECA6EEDE /* table_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_builder.h; path = include/leveldb/table_builder.h; sourceTree = ""; }; + 32286B36029E0A0C5EF3CF7FACFDE828 /* es-PA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PA.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-PA.lproj"; sourceTree = ""; }; + 325AFB4CBACC98A3F8EC79BF19DDAE61 /* Firebase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.debug.xcconfig; sourceTree = ""; }; + 327D01056854E2B13B40561F172984A5 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + 32A025FC7AA44B6340F0B3D3ECAE5675 /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 32EB05EE903C50A94CD83EE48DC0E872 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + 331717291051CAD5BB3353BB8C494A50 /* FIRAuthRequestConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthRequestConfiguration.m; path = FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.m; sourceTree = ""; }; + 331968F42465E8E681660A4F9DE033FF /* hi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hi.lproj; path = Auth/FirebaseAuthUI/Strings/hi.lproj; sourceTree = ""; }; + 331D5AAD7CCB53498DF832B15B48EB0B /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + 3321CB5DB4DF1C493E717FC8351C71A4 /* FPersistentConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistentConnection.h; path = Firebase/Database/Core/FPersistentConnection.h; sourceTree = ""; }; + 332B6F1DCD90DD0A9FABF2C8718B4F0B /* OIDExternalUserAgentIOS.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDExternalUserAgentIOS.m; path = Source/AppAuth/iOS/OIDExternalUserAgentIOS.m; sourceTree = ""; }; + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FBLPromises.framework; path = PromisesObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 334EAB92C832A8B1A25E76ED920D2F60 /* FIRAuthDefaultUIDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthDefaultUIDelegate.m; path = FirebaseAuth/Sources/Utilities/FIRAuthDefaultUIDelegate.m; sourceTree = ""; }; + 33AF2BEA19AA92B905791B5D2A1C4AF7 /* FIRStorageObservableTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageObservableTask.m; path = FirebaseStorage/Sources/FIRStorageObservableTask.m; sourceTree = ""; }; + 33E64FB96AE1E5878000B5A0DF0ED00C /* GULLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerLevel.h; path = GoogleUtilities/Logger/Public/GULLoggerLevel.h; sourceTree = ""; }; + 34194FA899C7983A97CFA1667E3666D9 /* FUIStaticContentTableViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIStaticContentTableViewController.h; path = Auth/FirebaseAuthUI/FUIStaticContentTableViewController.h; sourceTree = ""; }; + 342865614E6D95B35DC5F1180BF36A4B /* FirebaseCoreDiagnostics-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCoreDiagnostics-Info.plist"; sourceTree = ""; }; + 349D453606D972CC4125A9235D6AEFEA /* FBLPromise+Validate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Validate.m"; path = "Sources/FBLPromises/FBLPromise+Validate.m"; sourceTree = ""; }; + 34B5C51512525AB5568CAA468C878994 /* db_iter.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_iter.cc; path = db/db_iter.cc; sourceTree = ""; }; + 34E09E61F0F6E3E1246806D150640883 /* FLeafNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLeafNode.m; path = Firebase/Database/Snapshot/FLeafNode.m; sourceTree = ""; }; + 34EE00313A78D550D8644DDF8C527845 /* GTMAppAuthFetcherAuthorization+Keychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GTMAppAuthFetcherAuthorization+Keychain.m"; path = "Source/GTMAppAuthFetcherAuthorization+Keychain.m"; sourceTree = ""; }; + 34EEF89628756CF6DADFCF6F7FEF044C /* FNamedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNamedNode.h; path = Firebase/Database/FNamedNode.h; sourceTree = ""; }; + 34FC53C97C18D26AB932C5045350269D /* FIRDatabaseConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseConfig.m; path = Firebase/Database/Api/FIRDatabaseConfig.m; sourceTree = ""; }; + 35A44EC21C676A28BC2A89DDC04107F9 /* FUIAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthProvider.h; path = Auth/FirebaseAuthUI/FUIAuthProvider.h; sourceTree = ""; }; + 35BA381B397060FDA499255FBF1E626D /* GTMSessionFetcher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMSessionFetcher-prefix.pch"; sourceTree = ""; }; + 35CAD52DBF73AB5BE8FA7BD10435643E /* FIRStorageUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUtils.h; path = FirebaseStorage/Sources/FIRStorageUtils.h; sourceTree = ""; }; + 368C961A58263B15D8230CEE52FB897B /* FEventEmitter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventEmitter.h; path = Firebase/Database/Utilities/FEventEmitter.h; sourceTree = ""; }; + 369A1A5944F95579358CD6744CA18E2F /* FIRFacebookAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFacebookAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthCredential.m; sourceTree = ""; }; + 36CA67D99FD590B97C671527224321D3 /* GTMSessionUploadFetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionUploadFetcher.m; path = Source/GTMSessionUploadFetcher.m; sourceTree = ""; }; + 370DC54124A24E6D2D89067F66C8807D /* FIRStorageGetMetadataTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageGetMetadataTask.m; path = FirebaseStorage/Sources/FIRStorageGetMetadataTask.m; sourceTree = ""; }; + 371A2FCFDB806C4E3FDC7EDD27A1603D /* FIRGetProjectConfigRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetProjectConfigRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.m; sourceTree = ""; }; + 371F7C2003CB9DDACB528B7500A18ECB /* FUIAccountSettingsOperationSignOut.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationSignOut.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.m; sourceTree = ""; }; + 3739C5F655F31DED05B46617ABCB9412 /* OIDAuthorizationService+IOS.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OIDAuthorizationService+IOS.h"; path = "Source/AppAuth/iOS/OIDAuthorizationService+IOS.h"; sourceTree = ""; }; + 376319FF589FAE9CFBD2895D95DB64AD /* FUIAuthStrings.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthStrings.m; path = Auth/FirebaseAuthUI/FUIAuthStrings.m; sourceTree = ""; }; + 376756AE54DA1CDF00DF5DE0090FE3FF /* OIDAuthorizationService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthorizationService.h; path = Source/AppAuthCore/OIDAuthorizationService.h; sourceTree = ""; }; + 3785DF72C6DCAF47AE366F2829ABEDF0 /* FNamedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNamedNode.m; path = Firebase/Database/FNamedNode.m; sourceTree = ""; }; + 3795D22043104C7331249E54D65FDCBD /* kn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = kn.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/kn.lproj; sourceTree = ""; }; + 37C9A4444EFAAC11218633CD24F8D1DB /* he.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = he.lproj; path = Auth/FirebaseAuthUI/Strings/he.lproj; sourceTree = ""; }; + 37F19532C1B98CB916ADC4049AD0646E /* FIRAuthWebUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthWebUtils.h; path = FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h; sourceTree = ""; }; + 383473E33BC32486A7A364A9BB0E95C7 /* kn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = kn.lproj; path = Auth/FirebaseAuthUI/Strings/kn.lproj; sourceTree = ""; }; + 38579428D05E6E50944B74FAE19B1BB7 /* FIRVerifyAssertionResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyAssertionResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h; sourceTree = ""; }; + 385F5602994D5DE9145DB82DBDBBECB8 /* no_destructor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = no_destructor.h; path = util/no_destructor.h; sourceTree = ""; }; + 38B690DCEA9427D80930EAB58024467C /* FIRStorageTaskSnapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTaskSnapshot.h; path = FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h; sourceTree = ""; }; + 38C591D4DAB923A59C4FB29164568937 /* FEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEmptyNode.h; path = Firebase/Database/Snapshot/FEmptyNode.h; sourceTree = ""; }; + 38DB566120E8E842EE7213F780372006 /* FIRConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRConfiguration.m; path = FirebaseCore/Sources/FIRConfiguration.m; sourceTree = ""; }; + 38DFC526013A1EB3ABF8DE3A65E8E47D /* FUIAccountSettingsOperationForgotPassword.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationForgotPassword.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.m; sourceTree = ""; }; + 3958033B920F8ED4E9D12BB4DC6794E2 /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Frameworks/FIRAnalyticsConnector.framework; sourceTree = ""; }; + 39720C2178180584478CFED5FB451DA5 /* FirebaseStorage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseStorage-dummy.m"; sourceTree = ""; }; + 3973CC931936DEF986B63B91514EEE6A /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + 3975E8FFC67926A0E8DD39BDCBA4B16D /* FPersistenceManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistenceManager.m; path = Firebase/Database/Persistence/FPersistenceManager.m; sourceTree = ""; }; + 39ABF5B68E7A7B653EB64EC5D2D49DCD /* FValueEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueEventRegistration.h; path = Firebase/Database/Core/View/FValueEventRegistration.h; sourceTree = ""; }; + 39D2B86BB6BAD94CA0B74548C99551B5 /* pt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pt.lproj; path = Auth/FirebaseAuthUI/Strings/pt.lproj; sourceTree = ""; }; + 39FCF7E01DE23C18562782A5899B4D4C /* version_set.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_set.cc; path = db/version_set.cc; sourceTree = ""; }; + 3A0BE22AF48CFFC11F35F50CA46D4256 /* FIRAuthUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthUserDefaults.m; path = FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.m; sourceTree = ""; }; + 3A26EC884A9999B199DC3FAA4137C4AB /* GDTCORAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORAssert.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h; sourceTree = ""; }; + 3A3B1BAC7E72143AD4BA76261839C839 /* FIRStorageGetDownloadURLTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageGetDownloadURLTask.m; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m; sourceTree = ""; }; + 3A44B8B2E53063933C325653CE73494F /* FIRStorageErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageErrors.m; path = FirebaseStorage/Sources/FIRStorageErrors.m; sourceTree = ""; }; + 3A64636DD51D9160A5B0AA9214A30129 /* FIRComponentContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentContainer.m; path = FirebaseCore/Sources/FIRComponentContainer.m; sourceTree = ""; }; + 3AB38AF65C51703D0C443B947C88594F /* es-PE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PE.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PE.lproj"; sourceTree = ""; }; + 3B88E94C33408BA3A4273682782F14A5 /* FIRStorageListResult_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListResult_Private.h; path = FirebaseStorage/Sources/FIRStorageListResult_Private.h; sourceTree = ""; }; + 3B89883354B04E7224B4BCA94DCD089D /* FWriteTreeRef.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTreeRef.h; path = Firebase/Database/Core/FWriteTreeRef.h; sourceTree = ""; }; + 3B8F0DF9464867C7A2D721321F226F49 /* FIRDataSnapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot.h; path = Firebase/Database/Public/FIRDataSnapshot.h; sourceTree = ""; }; + 3BCF2E04232FF1193F3C043072D64FF8 /* es-AR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-AR.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-AR.lproj"; sourceTree = ""; }; + 3BF88DFDB9B0042674BFDE9F60D51C7C /* FUIGoogleAuth.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIGoogleAuth.m; path = GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.m; sourceTree = ""; }; + 3C045B91D80FD301D382461F3767A8CD /* FUIAuthPickerViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthPickerViewController.h; path = Auth/FirebaseAuthUI/FUIAuthPickerViewController.h; sourceTree = ""; }; + 3C891BDA225BAD436CEF7AF7F1695ACD /* FRangedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangedFilter.m; path = Firebase/Database/FRangedFilter.m; sourceTree = ""; }; + 3CAEE40E2A06A4534FC90D028269EEAE /* FBLPromise+Delay.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Delay.h"; path = "Sources/FBLPromises/include/FBLPromise+Delay.h"; sourceTree = ""; }; + 3D06E70882D19FEFCE28914350700F23 /* FIRSignInWithGameCenterRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSignInWithGameCenterRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.m; sourceTree = ""; }; + 3D39D997779449D74727241923F8597A /* GoogleDataTransport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransport-dummy.m"; sourceTree = ""; }; + 3D5C7F511F0129F1612DE2D4A8CE947B /* FirebaseInstallations.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstallations.release.xcconfig; sourceTree = ""; }; + 3D664A23B168D6D45A0115AFEAB24697 /* FIRStorageMetadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageMetadata.h; path = FirebaseStorage/Sources/Public/FIRStorageMetadata.h; sourceTree = ""; }; + 3D67CC9E38C38BB28F7D6453E84A0E1B /* env.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env.cc; path = util/env.cc; sourceTree = ""; }; + 3D96CCF8A1C3B80683E8A3C1767636D2 /* NSData+SRB64Additions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+SRB64Additions.h"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h"; sourceTree = ""; }; + 3E1FAFA86993C6014868FA31E61087E0 /* FChildrenNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildrenNode.h; path = Firebase/Database/Snapshot/FChildrenNode.h; sourceTree = ""; }; + 3E258FDF1B764B343037CC2895777F91 /* FirebaseCore-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCore-umbrella.h"; sourceTree = ""; }; + 3E9941705FB79B209ED37BD90A5D902B /* FIRInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallations.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallations.h; sourceTree = ""; }; + 3EA0C271CB77739BABDAAFE7F7636239 /* FIRStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorage.m; path = FirebaseStorage/Sources/FIRStorage.m; sourceTree = ""; }; + 3EB529903C3343CDA096444732E78D38 /* OIDFieldMapping.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDFieldMapping.h; path = Source/AppAuthCore/OIDFieldMapping.h; sourceTree = ""; }; + 3ECDE361BF011270F99FEB1A9A3B6FE9 /* FNodeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNodeFilter.h; path = Firebase/Database/Core/View/Filter/FNodeFilter.h; sourceTree = ""; }; + 3EEAF9534B473AD61A7AB54C40B9FEF1 /* write_batch.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = write_batch.cc; path = db/write_batch.cc; sourceTree = ""; }; + 3F1B7DBC84792CBABEBA9ECF5DBBB256 /* ms.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ms.lproj; path = Auth/FirebaseAuthUI/Strings/ms.lproj; sourceTree = ""; }; + 3F35FE6C627EEBD84D320623CBC3ED59 /* es-CL.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CL.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-CL.lproj"; sourceTree = ""; }; + 3F990D243683DB1B69B7DD45FE31E6E7 /* FIRFinalizeMFASignInResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFinalizeMFASignInResponse.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInResponse.h; sourceTree = ""; }; + 3FD1B4C1246D643E9476438C28048FA8 /* AppAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = AppAuth.framework; path = AppAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3FFE94EC5AF860B62041D69B5EE9486A /* FSparseSnapshotTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSparseSnapshotTree.m; path = Firebase/Database/Core/FSparseSnapshotTree.m; sourceTree = ""; }; + 4006509B9A0C604BC5178AD2B58C0FCD /* FIRAdditionalUserInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAdditionalUserInfo.h; path = FirebaseAuth/Sources/Public/FIRAdditionalUserInfo.h; sourceTree = ""; }; + 402DDDB7F31C1C5CE3C227D44A4DECCC /* posix_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = posix_logger.h; path = util/posix_logger.h; sourceTree = ""; }; + 406E73A9D34FD1FB8B07E30E058567AF /* FTreeSortedDictionaryEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionaryEnumerator.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m; sourceTree = ""; }; + 40BE96E1BFC9CE018C8D910E77FE05E1 /* da.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = da.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/da.lproj; sourceTree = ""; }; + 40D807BDAEF7E00EC311084CEB3E716B /* FIRMultiFactorResolver+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRMultiFactorResolver+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver+Internal.h"; sourceTree = ""; }; + 40F945E679A09218AE09F90EED9F4FA2 /* es-EC.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-EC.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-EC.lproj"; sourceTree = ""; }; + 413021A56F2BD5431D883E691672D672 /* GTMSessionFetcherLogging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcherLogging.m; path = Source/GTMSessionFetcherLogging.m; sourceTree = ""; }; + 4195822B54AB8FA1BEA64F7C1983BAB7 /* mr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = mr.lproj; path = Auth/FirebaseAuthUI/Strings/mr.lproj; sourceTree = ""; }; + 41AB484DC0B19FB371A44E3934FCC0AD /* FIRVerifyClientRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyClientRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.m; sourceTree = ""; }; + 41C974DAB5B079CE71E75DB13DFC0CC7 /* FSRWebSocket.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSRWebSocket.m; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.m; sourceTree = ""; }; + 421A6056036673D61E690E9EAFD6A930 /* Pods-MyExperiences-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-MyExperiences-Info.plist"; sourceTree = ""; }; + 42488D1FE841F575C61D519426D4364C /* OIDURLQueryComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDURLQueryComponent.h; path = Source/AppAuthCore/OIDURLQueryComponent.h; sourceTree = ""; }; + 4255E63440A44CE02AF3070690D0C948 /* GULLoggerCodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerCodes.h; path = GoogleUtilities/Common/GULLoggerCodes.h; sourceTree = ""; }; + 4255EAE792EEC21FF83A733F61479D97 /* GTMGatherInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMGatherInputStream.h; path = Source/GTMGatherInputStream.h; sourceTree = ""; }; + 428A36C062A2962BC3100F2C0FC17BB3 /* FUIAccountSettingsOperationUpdatePassword.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationUpdatePassword.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.m; sourceTree = ""; }; + 42914413BA6F0875F89E6B59303ACC41 /* es-CR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CR.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-CR.lproj"; sourceTree = ""; }; + 4292BBBC71583AC274A17B5EA2DEA043 /* GoogleUtilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleUtilities-Info.plist"; sourceTree = ""; }; + 42C7BFFB0E3DE1C0DDD9CA158FDDF6D6 /* GULSceneDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler.h; path = GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h; sourceTree = ""; }; + 42F6E008885453176BC7D27CA366F6C1 /* fr-CH.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "fr-CH.lproj"; path = "Auth/FirebaseAuthUI/Strings/fr-CH.lproj"; sourceTree = ""; }; + 431F138349D4FE38FA96998F33938388 /* ko.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ko.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ko.lproj; sourceTree = ""; }; + 4322D71552AD5DA1FD0A28B69543F2A1 /* FIRMultiFactorAssertion+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRMultiFactorAssertion+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion+Internal.h"; sourceTree = ""; }; + 4376CE82EF1BF0ECFA794D85F3766F87 /* ic_visibility_off.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_visibility_off.png; path = Auth/FirebaseAuthUI/Resources/ic_visibility_off.png; sourceTree = ""; }; + 4383A93D64CCC99B231FE7ECB7CB0C6B /* FTuplePathValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTuplePathValue.h; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.h; sourceTree = ""; }; + 43B1E4CD7B30B9FD278100133C2AC788 /* FirebaseAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseAuth.framework; path = FirebaseAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 43C43DE3698D5BA2BF456C6F2F7532C7 /* FIRUserInfoImpl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUserInfoImpl.h; path = FirebaseAuth/Sources/User/FIRUserInfoImpl.h; sourceTree = ""; }; + 444161411F02B826835C81A17C1E4285 /* ar.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ar.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ar.lproj; sourceTree = ""; }; + 448F29393FE115605D5CA3B7F9E3C564 /* FIndexedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedFilter.h; path = Firebase/Database/Core/View/Filter/FIndexedFilter.h; sourceTree = ""; }; + 44D2EDB1270B1F582810B370AB8F2F1A /* FIRAdditionalUserInfo_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAdditionalUserInfo_Internal.h; path = FirebaseAuth/Sources/User/FIRAdditionalUserInfo_Internal.h; sourceTree = ""; }; + 44D9AD5C042BBE2D118A698A9E5E76EF /* GDTCORReachability_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h; sourceTree = ""; }; + 451DB994D279FCD5DC50A8225E9DEDAE /* AppAuth.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AppAuth.release.xcconfig; sourceTree = ""; }; + 45C09F6B2C40752E3427CB95ECEC8ACC /* sk.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sk.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/sk.lproj; sourceTree = ""; }; + 45D210693C8C1852BEDCE2218C997AB2 /* FIRInstallationsIDController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIDController.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h; sourceTree = ""; }; + 45D396EDB48B3E1CED1969E1ABD6A9A1 /* cs.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = cs.lproj; path = Auth/FirebaseAuthUI/Strings/cs.lproj; sourceTree = ""; }; + 45E11AF46771013BD558C58EA9770182 /* FAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAuthTokenProvider.h; path = Firebase/Database/Login/FAuthTokenProvider.h; sourceTree = ""; }; + 46208F8F4DA72F736C3CA97FBF8633E5 /* GTMAppAuth.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GTMAppAuth.release.xcconfig; sourceTree = ""; }; + 462E033744D3959BB491ED645DF42A70 /* FirebaseAuth.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAuth.release.xcconfig; sourceTree = ""; }; + 463D1EAEEBD47D9938BCF8A662DC6A86 /* FIRNoopAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRNoopAuthTokenProvider.m; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.m; sourceTree = ""; }; + 46537E48C5450772F4B264F790FD1694 /* en-AU.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-AU.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-AU.lproj"; sourceTree = ""; }; + 469ADEDE390A439862C502366722D677 /* GTMSessionFetcher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GTMSessionFetcher-dummy.m"; sourceTree = ""; }; + 46A8D09E3ABE20DB3AF5BCBC70C770B6 /* FBLPromise+Async.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Async.m"; path = "Sources/FBLPromises/FBLPromise+Async.m"; sourceTree = ""; }; + 46CA62F34B2D8C856819BEB8C5215DA1 /* FUIAccountSettingsViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIAccountSettingsViewController.xib; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.xib; sourceTree = ""; }; + 4730405FFEC430182522451A957E885E /* FUIAuthTableViewCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthTableViewCell.m; path = Auth/FirebaseAuthUI/FUIAuthTableViewCell.m; sourceTree = ""; }; + 473112A3CDA01CDBEC8924CAD7682B96 /* FIRAuthBackend.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthBackend.m; path = FirebaseAuth/Sources/Backend/FIRAuthBackend.m; sourceTree = ""; }; + 477A700BD923CF5A1643043ADC94EC97 /* FIRSetAccountInfoRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSetAccountInfoRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.h; sourceTree = ""; }; + 477B26F19AC7827CEAF7052AEAF4F1D1 /* FTypedefs_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs_Private.h; path = Firebase/Database/Api/Private/FTypedefs_Private.h; sourceTree = ""; }; + 477FFB4052347BAD985B3A94763834BC /* FIRAuthWebUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthWebUtils.m; path = FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.m; sourceTree = ""; }; + 47BF9B1F1B231A09680C4D56CCE235B4 /* nanopb.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.release.xcconfig; sourceTree = ""; }; + 48914A7BA911F9F5780304712CAA8770 /* filter_block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_block.h; path = table/filter_block.h; sourceTree = ""; }; + 48B6C0DC5B6FA45680468DD2690747C7 /* two_level_iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = two_level_iterator.h; path = table/two_level_iterator.h; sourceTree = ""; }; + 48BCA366BED224540BBF9225961D5874 /* FIRAuthTokenResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthTokenResult.h; path = FirebaseAuth/Sources/Public/FIRAuthTokenResult.h; sourceTree = ""; }; + 48FAFEB26DDA963B5ADB9B5659C279A4 /* GDTCORTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h; sourceTree = ""; }; + 48FF0BF87B15F6A87546A37B2BE1679A /* OIDDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDDefines.h; path = Source/AppAuthCore/OIDDefines.h; sourceTree = ""; }; + 4900DB7C20F8911744B754D0004709A8 /* FBLPromises.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromises.h; path = Sources/FBLPromises/include/FBLPromises.h; sourceTree = ""; }; + 493BF9F147B5C3D81A03760D93753452 /* FIRConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfiguration.h; path = FirebaseCore/Sources/Public/FIRConfiguration.h; sourceTree = ""; }; + 494F76FE5143C8D636FE5CAB2CA7372A /* FIRPhoneMultiFactorAssertion+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRPhoneMultiFactorAssertion+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion+Internal.h"; sourceTree = ""; }; + 49628C5F8E59FEC789DFD126F5FCB1A3 /* db_impl.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_impl.cc; path = db/db_impl.cc; sourceTree = ""; }; + 49A0147206768735137648B732ADD53C /* FIRAuthProtoStartMFAPhoneRequestInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProtoStartMFAPhoneRequestInfo.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.h; sourceTree = ""; }; + 49A415C83A5EB9C040FDD6EEC57B55E2 /* FImmutableTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableTree.m; path = Firebase/Database/Core/Utilities/FImmutableTree.m; sourceTree = ""; }; + 49F63393A9E80EBBF65F56B5EDB54614 /* es-SV.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-SV.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-SV.lproj"; sourceTree = ""; }; + 4A4CBF036EE62FFEBB150AB9227C0939 /* es-GT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-GT.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-GT.lproj"; sourceTree = ""; }; + 4AF11B4252EB3995828F722EF9E7BB66 /* OIDURLSessionProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDURLSessionProvider.h; path = Source/AppAuthCore/OIDURLSessionProvider.h; sourceTree = ""; }; + 4B507101B953E5884032D7D3E1792371 /* FIRCoreDiagnosticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsInterop.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h; sourceTree = ""; }; + 4B57B1D12A80733844C26CC43FC19593 /* uk.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = uk.lproj; path = Auth/FirebaseAuthUI/Strings/uk.lproj; sourceTree = ""; }; + 4B7D65B60CA4A510AF8323E801381667 /* filter_policy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_policy.h; path = include/leveldb/filter_policy.h; sourceTree = ""; }; + 4BA61BB6DA2B3B8637F8722F9AA18F5F /* GULReachabilityChecker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityChecker.h; path = GoogleUtilities/Reachability/Private/GULReachabilityChecker.h; sourceTree = ""; }; + 4BD64D667BE6E644D010A4C6AB245206 /* sv.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sv.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/sv.lproj; sourceTree = ""; }; + 4C33F929C488C2621B9F88ED675801ED /* hu.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hu.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/hu.lproj; sourceTree = ""; }; + 4C544C318DE1B07A1D697B0F86F8E333 /* FIRStartMFASignInResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStartMFASignInResponse.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInResponse.m; sourceTree = ""; }; + 4C634386C4AF3FD1EBC5CEFEF84C46AC /* windows_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = windows_logger.h; path = util/windows_logger.h; sourceTree = ""; }; + 4C83DEDF6D65FAC677439496F70A8003 /* FIRAuthInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInterop.h; path = Interop/Auth/Public/FIRAuthInterop.h; sourceTree = ""; }; + 4CAC46B5F4A304C75A40CC264D52033F /* testharness.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testharness.h; path = util/testharness.h; sourceTree = ""; }; + 4CC5AD85024AEFCE15D5BB20FF5DE604 /* db.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db.h; path = include/leveldb/db.h; sourceTree = ""; }; + 4CDD262BE955BCCD50139C26B4E1B37C /* FQueryParams.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQueryParams.m; path = Firebase/Database/Core/FQueryParams.m; sourceTree = ""; }; + 4CEB318E95935B837B5592E7BE729383 /* FBLPromise+Race.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Race.m"; path = "Sources/FBLPromises/FBLPromise+Race.m"; sourceTree = ""; }; + 4D4712F06B0944FE3AF1EE789281B047 /* FPendingPut.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPendingPut.m; path = Firebase/Database/Persistence/FPendingPut.m; sourceTree = ""; }; + 4D79E78D7503509C5FB9CECC26794CC1 /* OIDExternalUserAgentIOSCustomBrowser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDExternalUserAgentIOSCustomBrowser.m; path = Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.m; sourceTree = ""; }; + 4D7BA2171283849317F64AD374A314EA /* FBLPromiseError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromiseError.m; path = Sources/FBLPromises/FBLPromiseError.m; sourceTree = ""; }; + 4E24B05160E278D466B32F147A97FE68 /* GULKeychainUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULKeychainUtils.m; path = GoogleUtilities/Environment/SecureStorage/GULKeychainUtils.m; sourceTree = ""; }; + 4E5F43CF7B994C577E41DD7E44C33231 /* FBLPromise+Do.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Do.h"; path = "Sources/FBLPromises/include/FBLPromise+Do.h"; sourceTree = ""; }; + 4E6CE7028A24474F1C666BEEC7568971 /* FIRVerifyClientResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyClientResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.m; sourceTree = ""; }; + 4F2E84C3E82B88B41FC14399D96AFF7E /* GULAppEnvironmentUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppEnvironmentUtil.h; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h; sourceTree = ""; }; + 4F423EDD6CE2FAB275E51626151E9B5B /* GDTCCTUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTUploader.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h; sourceTree = ""; }; + 4FBD09FC244F8C77BA89C81EB61375D1 /* OIDScopes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDScopes.h; path = Source/AppAuthCore/OIDScopes.h; sourceTree = ""; }; + 4FBDA9871C1CC5320359E77952F468C2 /* FIRCoreDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsData.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h; sourceTree = ""; }; + 4FD4FE57FB9B916510FB562EE2A4BE10 /* FIRStorageObservableTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageObservableTask_Private.h; path = FirebaseStorage/Sources/FIRStorageObservableTask_Private.h; sourceTree = ""; }; + 5007EEBF4BE55DB72D5EE4CAA00E4C5C /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + 504B0D1BEED943ACA979474FA55362FE /* FDataEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FDataEvent.m; path = Firebase/Database/Core/View/FDataEvent.m; sourceTree = ""; }; + 505214DCA8CABD3F660E0A6ACD5A60B8 /* FTupleOnDisconnect.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleOnDisconnect.h; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h; sourceTree = ""; }; + 505DC4F2361DB07F86AC3E424C21849A /* FIndexedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedNode.m; path = Firebase/Database/Snapshot/FIndexedNode.m; sourceTree = ""; }; + 50678D93A7A086BDB66C72F4A47CC647 /* FTypedefs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs.h; path = Firebase/Database/Utilities/FTypedefs.h; sourceTree = ""; }; + 50869C4A83B8711B77611300BCA59CB6 /* Pods-MyExperiences-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-MyExperiences-dummy.m"; sourceTree = ""; }; + 509507A836C0211E77888E451937CC3C /* FIRVerifyPasswordRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyPasswordRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordRequest.h; sourceTree = ""; }; + 50BD34FADDD845EBC8222D9EB3995F05 /* FBLPromise+Timeout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Timeout.h"; path = "Sources/FBLPromises/include/FBLPromise+Timeout.h"; sourceTree = ""; }; + 5119B34C2C5AA2AE16AE4B3BA48C5532 /* pb_common.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_common.c; sourceTree = ""; }; + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseDatabase.framework; path = FirebaseDatabase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 51B79EA8514AB2DE5FB6E83BADD37011 /* FUIAuthTableHeaderView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthTableHeaderView.m; path = Auth/FirebaseAuthUI/FUIAuthTableHeaderView.m; sourceTree = ""; }; + 5219D7E4DCD40901B20474422BEB8E0D /* FIRInstallationsSingleOperationPromiseCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsSingleOperationPromiseCache.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h; sourceTree = ""; }; + 5269D9C7D55A1DA1FED6C3B459D98F96 /* GTMSessionFetcher.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GTMSessionFetcher.release.xcconfig; sourceTree = ""; }; + 533A075CC6706D52D274E374A6C5F9DD /* FKeyIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeyIndex.h; path = Firebase/Database/FKeyIndex.h; sourceTree = ""; }; + 53F0F09CD2905B3297B81557EFD55B0F /* FirebaseAnalytics.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.debug.xcconfig; sourceTree = ""; }; + 5400A145F328381BD52F9A9ACF4C7A06 /* GoogleSignIn.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = GoogleSignIn.bundle; path = Resources/GoogleSignIn.bundle; sourceTree = ""; }; + 5404F30E0CBEEC5274DCB96F2A740A85 /* FBLPromise+Any.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Any.m"; path = "Sources/FBLPromises/FBLPromise+Any.m"; sourceTree = ""; }; + 5440B26AAF05B19A6349A85F31249BF6 /* FIRPhoneAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRPhoneAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthProvider.m; sourceTree = ""; }; + 544356950C800EB743CC174C9ABFCCE8 /* FIRInstallationsStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStore.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m; sourceTree = ""; }; + 54A0D35E86F62F0B4BD48A8412384F5A /* FKeepSyncedEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeepSyncedEventRegistration.h; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.h; sourceTree = ""; }; + 54C343323DA324F133310E331A56EC54 /* GDTCCTNanopbHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTNanopbHelpers.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m; sourceTree = ""; }; + 55736272F08581E91E4043F8CE9E5C23 /* memtable.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = memtable.cc; path = db/memtable.cc; sourceTree = ""; }; + 55921E5AC59C99C61E45F4771E6881C9 /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + 55A5039F460D923DB08EEE1CBDE8081D /* bg.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = bg.lproj; path = Auth/FirebaseAuthUI/Strings/bg.lproj; sourceTree = ""; }; + 55D4FCD5BAA0A7583F30CF79D5F369A7 /* FIRSendVerificationCodeResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSendVerificationCodeResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.m; sourceTree = ""; }; + 55E877FAB1A07AA39659E1E33B454A34 /* FIRAuthGlobalWorkQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthGlobalWorkQueue.h; path = FirebaseAuth/Sources/Auth/FIRAuthGlobalWorkQueue.h; sourceTree = ""; }; + 55ED76CB4443F7E041AB9AC6FA9AAB50 /* GULNetworkLoggerProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkLoggerProtocol.h; path = GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h; sourceTree = ""; }; + 5604269047012A590F82880FF4FB18B8 /* FIRMultiFactorResolver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMultiFactorResolver.h; path = FirebaseAuth/Sources/Public/FIRMultiFactorResolver.h; sourceTree = ""; }; + 562417974B48784FF00BE78597B8C019 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProtoFinalizeMFAPhoneResponseInfo.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneResponseInfo.h; sourceTree = ""; }; + 5674BB3E7376B13F3BFA81723D39ABC5 /* GoogleDataTransportCCTSupport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransportCCTSupport-dummy.m"; sourceTree = ""; }; + 56BFB5377F78090CCC71859F9C435F83 /* OIDServiceDiscovery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDServiceDiscovery.m; path = Source/AppAuthCore/OIDServiceDiscovery.m; sourceTree = ""; }; + 570063252316BB9DC95F50B0BEC2AE1C /* FNextPushId.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNextPushId.h; path = Firebase/Database/Utilities/FNextPushId.h; sourceTree = ""; }; + 572768369632698FD67E08A6CBE5E65F /* FirebaseAuthUI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseAuthUI.h; path = Auth/FirebaseAuthUI/FirebaseAuthUI.h; sourceTree = ""; }; + 573253504667D85EE768C19D3F939A99 /* FUIAuthTableViewCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIAuthTableViewCell.xib; path = Auth/FirebaseAuthUI/FUIAuthTableViewCell.xib; sourceTree = ""; }; + 573C2D9A17826A7450441A7FBCCD3014 /* FBLPromise+Delay.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Delay.m"; path = "Sources/FBLPromises/FBLPromise+Delay.m"; sourceTree = ""; }; + 57654CEC144ACD0FFCABF85243288B86 /* OIDIDToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDIDToken.h; path = Source/AppAuthCore/OIDIDToken.h; sourceTree = ""; }; + 576B91C11B11CCAE6FF3C083E2910102 /* GTMReadMonitorInputStream.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMReadMonitorInputStream.h; path = Source/GTMReadMonitorInputStream.h; sourceTree = ""; }; + 57D4AF8B6EB8F9379CB8F2631DF57FF2 /* OIDAuthStateErrorDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthStateErrorDelegate.h; path = Source/AppAuthCore/OIDAuthStateErrorDelegate.h; sourceTree = ""; }; + 580A2DF400B3703EDDEE080EF2686B80 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 580FEBB5E7903DF0A726E950419BFB5D /* GULOriginalIMPConvenienceMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULOriginalIMPConvenienceMacros.h; path = GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h; sourceTree = ""; }; + 58468784E905EC12C0878CEA8C1CA891 /* es-NI.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-NI.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-NI.lproj"; sourceTree = ""; }; + 584DB4080DC999B0DF412672F047EB69 /* GDTCORUploadPackage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h; sourceTree = ""; }; + 585ED8010AE1A4B72569E70262072162 /* OIDFieldMapping.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDFieldMapping.m; path = Source/AppAuthCore/OIDFieldMapping.m; sourceTree = ""; }; + 58B98A3CF9D1D67D9B4602B856D83CE1 /* FirebaseCoreDiagnostics-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCoreDiagnostics-umbrella.h"; sourceTree = ""; }; + 58C160DA81101F1D0015E334D29C329E /* OIDAuthState+IOS.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthState+IOS.m"; path = "Source/AppAuth/iOS/OIDAuthState+IOS.m"; sourceTree = ""; }; + 5A0D953E59A8DED28D3164EC06E93905 /* hr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hr.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/hr.lproj; sourceTree = ""; }; + 5A149ACDFEA3E4EA95378607B77D3B83 /* GDTCOREvent_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h; sourceTree = ""; }; + 5A17A81DAC159F24CE9466BA8B0DE04D /* FirebaseDatabase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseDatabase-umbrella.h"; sourceTree = ""; }; + 5A3DAD5C415A8443A0DA97DCE4BB1C5D /* FIRAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthCredential.h; path = FirebaseAuth/Sources/Public/FIRAuthCredential.h; sourceTree = ""; }; + 5A4A40F06A6A8E619437AE6C82A30FB8 /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 5A869C047DA714685FC173B0BEBCEC95 /* en-GB.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-GB.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-GB.lproj"; sourceTree = ""; }; + 5AD0170E1AE017F7BF65280EE7A9D1B5 /* FIRStorageMetadata_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageMetadata_Private.h; path = FirebaseStorage/Sources/FIRStorageMetadata_Private.h; sourceTree = ""; }; + 5B9D467DDC47ABB6AB58578D530578AB /* FConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConnection.m; path = Firebase/Database/Realtime/FConnection.m; sourceTree = ""; }; + 5BDDE1C8BDEA616246AD25A843C83C0B /* FIRStorageTaskSnapshot_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTaskSnapshot_Private.h; path = FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h; sourceTree = ""; }; + 5BF69E8882B8B2DB954A2A48042B84CF /* FIRMultiFactorInfo+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRMultiFactorInfo+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo+Internal.h"; sourceTree = ""; }; + 5C26D6616E92CB6CEF0C796513A00E7D /* FIRInstallationsAuthTokenResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResultInternal.h; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h; sourceTree = ""; }; + 5C363F15AA606162F501DEC2F1C3F71D /* FUIAuthSignInButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthSignInButton.h; path = Auth/FirebaseAuthUI/FUIAuthSignInButton.h; sourceTree = ""; }; + 5C403D3BDC74CA4BF92DE5C1E73CF160 /* GULNSData+zlib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULNSData+zlib.h"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"; sourceTree = ""; }; + 5E16797E9464DC13C0026A832D0C8518 /* FSyncPoint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncPoint.h; path = Firebase/Database/Core/FSyncPoint.h; sourceTree = ""; }; + 5E1B0586B157A28B1F1A35C9E6783268 /* GDTCORTargets.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTargets.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h; sourceTree = ""; }; + 5E2CA4028042B0790AE59AB6B90E6E8C /* es.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = es.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/es.lproj; sourceTree = ""; }; + 5E3B3028D10F8D06C2A88AF313F76CDC /* FUIStaticContentTableViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIStaticContentTableViewController.m; path = Auth/FirebaseAuthUI/FUIStaticContentTableViewController.m; sourceTree = ""; }; + 5E5F5A39D1BA88D7C06015AD44FDE98F /* hash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = hash.h; path = util/hash.h; sourceTree = ""; }; + 5E73E913D6BE2187678163C216DF1BB5 /* FClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FClock.m; path = Firebase/Database/FClock.m; sourceTree = ""; }; + 5E741077ED9CDA63CB0EE1E4387BB7B8 /* FIRAuthOperationType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthOperationType.h; path = FirebaseAuth/Sources/Auth/FIRAuthOperationType.h; sourceTree = ""; }; + 5E942549C86F57C477E3AC759C80C513 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 5EDAFAAD07C262D444664C5BD399E6FC /* FUIAccountSettingsOperationUpdateName.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationUpdateName.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.m; sourceTree = ""; }; + 5EFF3A22F1C48B4980A4B052C0875FD6 /* FIRStorageDownloadTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageDownloadTask.m; path = FirebaseStorage/Sources/FIRStorageDownloadTask.m; sourceTree = ""; }; + 5F4DC6177BD16CE479E33E760B8781E6 /* GULSceneDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSceneDelegateSwizzler.m; path = GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m; sourceTree = ""; }; + 5F642D548971EC7E8066481D6B7AEF05 /* FTupleRemovedQueriesEvents.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleRemovedQueriesEvents.m; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m; sourceTree = ""; }; + 5F76DC8A393D84B5EC545F11C33B1C04 /* FUIAccountSettingsOperationUpdateEmail.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationUpdateEmail.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.m; sourceTree = ""; }; + 5FD82FD67806944740A8EA55D55E725D /* FIROptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROptions.m; path = FirebaseCore/Sources/FIROptions.m; sourceTree = ""; }; + 6015A44958D8FCFD5AC5DD46D28EA3CB /* FIRAuthBackend+MultiFactor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRAuthBackend+MultiFactor.m"; path = "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.m"; sourceTree = ""; }; + 6024FDADF987F2A905E3FABFDCA3FAD1 /* en-ZA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-ZA.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-ZA.lproj"; sourceTree = ""; }; + 60470DBAAA6781680A41419A079C8788 /* fi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fi.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/fi.lproj; sourceTree = ""; }; + 605F66FBD87C009EECDEEFB5EFD3BACD /* FIRSetAccountInfoRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSetAccountInfoRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoRequest.m; sourceTree = ""; }; + 6068E3E88D5B4912A996A1E395BEB211 /* FIRAuthDataResult_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthDataResult_Internal.h; path = FirebaseAuth/Sources/Auth/FIRAuthDataResult_Internal.h; sourceTree = ""; }; + 6080376A14E37CCAB6B3B0C2BA0D0855 /* OIDAuthorizationService+IOS.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthorizationService+IOS.m"; path = "Source/AppAuth/iOS/OIDAuthorizationService+IOS.m"; sourceTree = ""; }; + 6097D15BF93E3419D955BD573255BC7B /* version_edit.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_edit.cc; path = db/version_edit.cc; sourceTree = ""; }; + 609ABC8D27C7BECC6DE50BB8016F27BF /* FIRCreateAuthURIResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCreateAuthURIResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.m; sourceTree = ""; }; + 60D6EAE2214B51D9C890BE3365E0543C /* FKeyIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeyIndex.m; path = Firebase/Database/FKeyIndex.m; sourceTree = ""; }; + 6109B697F6B52FD7D66B26A351F6A920 /* sv.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sv.lproj; path = Auth/FirebaseAuthUI/Strings/sv.lproj; sourceTree = ""; }; + 6148070EDD3BDC2C008E97051E5E51CB /* FIRAuthDataResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthDataResult.m; path = FirebaseAuth/Sources/Auth/FIRAuthDataResult.m; sourceTree = ""; }; + 614FD0C542050D26FA76C49E96603020 /* status.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = status.h; path = include/leveldb/status.h; sourceTree = ""; }; + 6189375E4157BB1E09D2728778079CC1 /* OIDScopeUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDScopeUtilities.m; path = Source/AppAuthCore/OIDScopeUtilities.m; sourceTree = ""; }; + 618B1E5DFBEC073ABD03719A3CBEC5A2 /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + 61AB353792B56B5B30FA24FA07336722 /* FBLPromise+Then.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Then.m"; path = "Sources/FBLPromises/FBLPromise+Then.m"; sourceTree = ""; }; + 61DACD2C6A7C9F8A229EF0ADE870DE2A /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + 61FECAF9DDCFEB0AAC6EB34E1F4E9795 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + 622905E4C7B48388FBFAEB5B4885A636 /* GDTCORPlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORPlatform.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m; sourceTree = ""; }; + 6259D501189F90B7AE0391DF9109BD35 /* GULKeychainUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULKeychainUtils.h; path = GoogleUtilities/Environment/Public/GULKeychainUtils.h; sourceTree = ""; }; + 625AF7810C28799EFD82E03BD62AC283 /* GTMAppAuth-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GTMAppAuth-Info.plist"; sourceTree = ""; }; + 62B5C69DF77E1FC8B2CC1480BB7776A2 /* GTMOAuth2KeychainCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMOAuth2KeychainCompatibility.h; path = Source/GTMOAuth2KeychainCompatibility/GTMOAuth2KeychainCompatibility.h; sourceTree = ""; }; + 62C87D6A9A8CBCDE954AE13FC94E21EF /* FWriteTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTree.h; path = Firebase/Database/Core/FWriteTree.h; sourceTree = ""; }; + 62D83D6764BFFF792BDF8BCD6FA8DC76 /* block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block.h; path = table/block.h; sourceTree = ""; }; + 62E8321425614316CDA53111C50B49A1 /* FirebaseInstallations.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstallations.debug.xcconfig; sourceTree = ""; }; + 62F454249D6AA95C313D27B86A06B4F4 /* FirebaseUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseUI.framework; path = FirebaseUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 62FF2415F7CE0F63E2A28F7B9E7F203F /* FBLPromise+Testing.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Testing.m"; path = "Sources/FBLPromises/FBLPromise+Testing.m"; sourceTree = ""; }; + 6301E5CDD1DED7CBC74026B7B30735C4 /* FUIAuthErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthErrors.m; path = Auth/FirebaseAuthUI/FUIAuthErrors.m; sourceTree = ""; }; + 634E60D54FACAEA3CDD23BC456EB97E0 /* GULAppEnvironmentUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppEnvironmentUtil.m; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m; sourceTree = ""; }; + 6350872202105F88AB9E4C49B955A981 /* GTMAppAuthFetcherAuthorization+Keychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GTMAppAuthFetcherAuthorization+Keychain.h"; path = "Source/GTMAppAuthFetcherAuthorization+Keychain.h"; sourceTree = ""; }; + 6354B7053086BB30B515EDE313EB0572 /* FirebaseCoreInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCoreInternal.h; path = FirebaseCore/Sources/Private/FirebaseCoreInternal.h; sourceTree = ""; }; + 6365C0AF9225C127A860B57949F71079 /* FTupleFirebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleFirebase.h; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.h; sourceTree = ""; }; + 636F5649D4AEAEE24280A6B1209EADFC /* env.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env.h; path = include/leveldb/env.h; sourceTree = ""; }; + 63BC3D605717332C4ECED77F0680FF1A /* GTMSessionFetcher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GTMSessionFetcher.modulemap; sourceTree = ""; }; + 6403E384584CBFB8805D55588F538224 /* iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator.h; path = include/leveldb/iterator.h; sourceTree = ""; }; + 64548224BB9A1948AEC7FB891E88BB5D /* FIRAuthAPNSTokenType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthAPNSTokenType.h; path = FirebaseAuth/Sources/Public/FIRAuthAPNSTokenType.h; sourceTree = ""; }; + 646E13F13038F5392591DBBD166BFDB3 /* FTupleSetIdPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleSetIdPath.h; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h; sourceTree = ""; }; + 64948C59CFBEBBCAC0EE75768B1A66F7 /* ro.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ro.lproj; path = Auth/FirebaseAuthUI/Strings/ro.lproj; sourceTree = ""; }; + 64EC6A649794171EB333535CC75C27F5 /* FIRVerifyPasswordResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyPasswordResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.h; sourceTree = ""; }; + 64F0158D39427082A58B66417D642EF2 /* FRangeMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangeMerge.m; path = Firebase/Database/Core/FRangeMerge.m; sourceTree = ""; }; + 64FDB8B8A3BAEE7F4E9AF31419F79891 /* FSRWebSocket.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSRWebSocket.h; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.h; sourceTree = ""; }; + 654BB45670AA13C68A7FBDF787179FBF /* GTMSessionFetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcher.m; path = Source/GTMSessionFetcher.m; sourceTree = ""; }; + 65B219104CD42208B88312DE148CB3A0 /* FBLPromise+Await.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Await.h"; path = "Sources/FBLPromises/include/FBLPromise+Await.h"; sourceTree = ""; }; + 65B5611A02B54AF167B839A5FB4E668E /* id.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = id.lproj; path = Auth/FirebaseAuthUI/Strings/id.lproj; sourceTree = ""; }; + 65CB8A235F0A6036357C260E72FF4F51 /* FIRAuthProtoStartMFAPhoneResponseInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProtoStartMFAPhoneResponseInfo.m; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.m; sourceTree = ""; }; + 65E2B99D595DB983880E6E49B6065571 /* FIRActionCodeSettings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRActionCodeSettings.h; path = FirebaseAuth/Sources/Public/FIRActionCodeSettings.h; sourceTree = ""; }; + 65E368CF321942CE98AAD10B26D0A07D /* FIRInstallationsErrorUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsErrorUtil.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m; sourceTree = ""; }; + 65EE3073A02E48ADF059D298867A4902 /* FIRGetOOBConfirmationCodeResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetOOBConfirmationCodeResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.m; sourceTree = ""; }; + 65FC5F7A295C348696803A456B61FBBF /* zh-Hant.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant.lproj"; path = "Auth/FirebaseAuthUI/Strings/zh-Hant.lproj"; sourceTree = ""; }; + 6617BF2CDA7A9B322A0459463CD349C3 /* GDTCORUploadPackage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h; sourceTree = ""; }; + 663809FA696517E7EBFAD50E9D78AD48 /* FChildChangeAccumulator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildChangeAccumulator.h; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h; sourceTree = ""; }; + 66390B4F65D06861288DF3E89EB760F4 /* en.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = en.lproj; path = Auth/FirebaseAuthUI/Strings/en.lproj; sourceTree = ""; }; + 66572644FE511ADF1DD46C07C47BB895 /* FUIAccountSettingsOperationUpdateEmail.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationUpdateEmail.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateEmail.h; sourceTree = ""; }; + 6664F046DE36C873274CEE8DFF2BECFD /* FIRAuthWebViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthWebViewController.h; path = FirebaseAuth/Sources/Utilities/FIRAuthWebViewController.h; sourceTree = ""; }; + 667D98F84E5FDD3D4D026D657ABB2756 /* FIRVerifyAssertionResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyAssertionResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.m; sourceTree = ""; }; + 6692BB174C22B5549DEEF4BC2AF49C6A /* Pods-MyExperiences.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-MyExperiences.modulemap"; sourceTree = ""; }; + 670E3A3782427E916EB9BB0D0B681559 /* filename.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filename.h; path = db/filename.h; sourceTree = ""; }; + 67159BAA40CC337613A80836DD8BF37D /* FIRMultiFactorAssertion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactorAssertion.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactorAssertion.m; sourceTree = ""; }; + 673E745E6EDF1CEA84454171E55EDA98 /* PromisesObjC.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PromisesObjC.modulemap; sourceTree = ""; }; + 6747BE4442C95908D4D28E8D1ABFAB76 /* FUIAccountSettingsOperationType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationType.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationType.h; sourceTree = ""; }; + 674D53C4BF02A9ACA05F1A27000C5EF7 /* table.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table.cc; path = table/table.cc; sourceTree = ""; }; + 676A757F81831B5D12A3413072F772B1 /* FIRVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVersion.h; path = FirebaseCore/Sources/FIRVersion.h; sourceTree = ""; }; + 678B1223F2BE90B1D127AB412F334E22 /* dbformat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dbformat.h; path = db/dbformat.h; sourceTree = ""; }; + 67A202C7FB39D4EF6220EB50BAA61AFE /* FIRStorageTokenAuthorizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTokenAuthorizer.h; path = FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h; sourceTree = ""; }; + 67F83985ACA93737DD4D45DB6C0CA19B /* FIRGetOOBConfirmationCodeResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetOOBConfirmationCodeResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h; sourceTree = ""; }; + 68428ACE363E5CFA4816A9F1B21640A8 /* FIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndex.m; path = Firebase/Database/FIndex.m; sourceTree = ""; }; + 68AB9C81F35DB8A4DCC516175E1F860C /* mutexlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mutexlock.h; path = util/mutexlock.h; sourceTree = ""; }; + 68C12C2F05F8845F2117F2E65E74EFDF /* OIDTokenResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDTokenResponse.m; path = Source/AppAuthCore/OIDTokenResponse.m; sourceTree = ""; }; + 68C28E759956387D8E25CBB6785BC93F /* GULSceneDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler_Private.h; path = GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h; sourceTree = ""; }; + 68C7EA4DCAD33358C682613FB0CDF819 /* th.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = th.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/th.lproj; sourceTree = ""; }; + 68C90E3FDA5545E6FD31403207BF27DC /* OIDExternalUserAgentCatalyst.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDExternalUserAgentCatalyst.m; path = Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.m; sourceTree = ""; }; + 68E6D55D2E5797DAEE6966BAFCF95C5F /* es-VE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-VE.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-VE.lproj"; sourceTree = ""; }; + 69279375BEBF6427D31ED9DC4A523D78 /* FBLPromise+All.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+All.m"; path = "Sources/FBLPromises/FBLPromise+All.m"; sourceTree = ""; }; + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransportCCTSupport.framework; path = GoogleDataTransportCCTSupport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 695E99910948F9E8E6793FC52BD6AA01 /* FIRAuthRequestConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthRequestConfiguration.h; path = FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h; sourceTree = ""; }; + 6969333C9227391D15AC78F611999F9B /* GTMSessionFetcher.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GTMSessionFetcher.debug.xcconfig; sourceTree = ""; }; + 69734D4AD914CB4493F17184D49AB7D6 /* FLLRBEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBEmptyNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m; sourceTree = ""; }; + 6998105EDEDFE89C9237A903E13AA4AA /* GULUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULUserDefaults.h; path = GoogleUtilities/UserDefaults/Private/GULUserDefaults.h; sourceTree = ""; }; + 69CE82213B430ED4CC3D6630855D6FBD /* FTreeNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeNode.h; path = Firebase/Database/Core/Utilities/FTreeNode.h; sourceTree = ""; }; + 69F44E5B36FA5106930486C4FA63C17B /* FirebaseCoreInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCoreInternal.h; path = FirebaseCore/Sources/Private/FirebaseCoreInternal.h; sourceTree = ""; }; + 69F8D7A867F609C67B74BB85FF357F12 /* FIRInstallationsSingleOperationPromiseCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsSingleOperationPromiseCache.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m; sourceTree = ""; }; + 6A639DDDCACAA82EDEE506C4020EF5A3 /* GDTCORRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORRegistrar.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m; sourceTree = ""; }; + 6AD16C64DC57BE00921DFB26B3E88660 /* GDTCORClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORClock.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h; sourceTree = ""; }; + 6ADA72465BC54012D2E01EF0E369AD84 /* th.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = th.lproj; path = Auth/FirebaseAuthUI/Strings/th.lproj; sourceTree = ""; }; + 6AFC363CB444A494A51C8E1CF891B276 /* FMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMerge.h; path = Firebase/Database/Core/Operation/FMerge.h; sourceTree = ""; }; + 6B0125857F5D4327999FD36E51BC633B /* FirebaseStorage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseStorage.debug.xcconfig; sourceTree = ""; }; + 6B307FF8DD426613C9E87912E8096331 /* repair.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = repair.cc; path = db/repair.cc; sourceTree = ""; }; + 6B74182157734B3092D8EFAF015E4B26 /* es-BO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-BO.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-BO.lproj"; sourceTree = ""; }; + 6BBAD787550D738C9C7AC6091D67E8E4 /* log_writer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_writer.h; path = db/log_writer.h; sourceTree = ""; }; + 6BDEEB8A7411C302E9837483C2298F14 /* GTMAppAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMAppAuth.h; path = Source/GTMAppAuth.h; sourceTree = ""; }; + 6C60370C2CB15E233982FF3A8D8E310E /* FirebaseAuth-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseAuth-Info.plist"; sourceTree = ""; }; + 6C8F2633D88D1F74962838B253D72FCE /* AppAuthCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AppAuthCore.h; path = Source/AppAuthCore.h; sourceTree = ""; }; + 6CA945041134FF42600B03386818A62D /* FUIAuthTableHeaderView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthTableHeaderView.h; path = Auth/FirebaseAuthUI/FUIAuthTableHeaderView.h; sourceTree = ""; }; + 6CD6E75538335D0C15F77F90238740C8 /* two_level_iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = two_level_iterator.cc; path = table/two_level_iterator.cc; sourceTree = ""; }; + 6CE086BF840833A55297E114A06C1101 /* AppAuth-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "AppAuth-Info.plist"; sourceTree = ""; }; + 6D30EF1C0685DD064607D8AC309AB8FE /* GULNSData+zlib.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GULNSData+zlib.m"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.m"; sourceTree = ""; }; + 6D5B40554AE06250C3560A070E872FD2 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 6E92ABD50E475C05DDFA7B0A5531B74A /* FIRGoogleAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGoogleAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.h; sourceTree = ""; }; + 6EA549DC6A9769196F50FEAAFE6F9D2E /* hr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hr.lproj; path = Auth/FirebaseAuthUI/Strings/hr.lproj; sourceTree = ""; }; + 6EE5385D046245271A0934FA76C066DF /* OIDTokenResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDTokenResponse.h; path = Source/AppAuthCore/OIDTokenResponse.h; sourceTree = ""; }; + 6EF13F13E0C7FAD491A17E36510E58B5 /* OIDErrorUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDErrorUtilities.m; path = Source/AppAuthCore/OIDErrorUtilities.m; sourceTree = ""; }; + 6F5C88B3CCB1162C269594E5A4400834 /* FConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConstants.h; path = Firebase/Database/Constants/FConstants.h; sourceTree = ""; }; + 6F6CB189D81B7A5D42DB2B7674676C63 /* FIRFinalizeMFASignInRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFinalizeMFASignInRequest.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.h; sourceTree = ""; }; + 6F86A1C28C6AA54FE5D0809FF096D7FA /* FIRInstallationsIIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDTokenStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m; sourceTree = ""; }; + 6FA2962149836A8999CDF110AAD149CC /* FBLPromise+Reduce.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Reduce.m"; path = "Sources/FBLPromises/FBLPromise+Reduce.m"; sourceTree = ""; }; + 6FB877E48D135890070C81A252F9515C /* FIRAuthUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthUserDefaults.h; path = FirebaseAuth/Sources/Storage/FIRAuthUserDefaults.h; sourceTree = ""; }; + 6FC01874018CA0C937F043AF841B3189 /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + 6FD122EA0AB9AB2A8FFA5F676C795DF0 /* GTMAppAuth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GTMAppAuth.framework; path = GTMAppAuth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6FDC8EC42195FA6009210D0F20D0C85F /* GTMAppAuth-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GTMAppAuth-dummy.m"; sourceTree = ""; }; + 6FE49F161741365656721C78D4163690 /* FSnapshotHolder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotHolder.h; path = Firebase/Database/Core/FSnapshotHolder.h; sourceTree = ""; }; + 70582D78CBEA51C33A8B82C9FFB723B1 /* ic_account_circle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_account_circle.png; path = Auth/FirebaseAuthUI/Resources/ic_account_circle.png; sourceTree = ""; }; + 706EA4C9C7E61F24F7B8DDB2437C8F9C /* FIRDataEventType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataEventType.h; path = Firebase/Database/Public/FIRDataEventType.h; sourceTree = ""; }; + 7082B9449622F069DA6D80470872D467 /* FUIAuthTableViewCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthTableViewCell.h; path = Auth/FirebaseAuthUI/FUIAuthTableViewCell.h; sourceTree = ""; }; + 70C7B1A3C16EB7A855387B627E028E99 /* FIRGameCenterAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGameCenterAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthProvider.m; sourceTree = ""; }; + 70F7778B9B8E61DC442DCB0479E095B5 /* histogram.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = histogram.h; path = util/histogram.h; sourceTree = ""; }; + 710C93802B6DFF2AC35E8AA400C51F01 /* FLimitedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLimitedFilter.m; path = Firebase/Database/Core/View/Filter/FLimitedFilter.m; sourceTree = ""; }; + 71548566AA12411F1169B351463A8EF1 /* FIRStorageErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageErrors.h; path = FirebaseStorage/Sources/FIRStorageErrors.h; sourceTree = ""; }; + 716DE49C140CA622BFAF92044E4F1E02 /* FTupleTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTransaction.m; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.m; sourceTree = ""; }; + 719D94D75C5E235B7C3E2F38110E1402 /* FListenComplete.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenComplete.h; path = Firebase/Database/FListenComplete.h; sourceTree = ""; }; + 71B0ED66B3AB0DEACE07CFB743EF1AB1 /* FRepoInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoInfo.m; path = Firebase/Database/Core/FRepoInfo.m; sourceTree = ""; }; + 7235427A1267E29C913763C2DD9508AF /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProtoFinalizeMFAPhoneRequestInfo.m; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoFinalizeMFAPhoneRequestInfo.m; sourceTree = ""; }; + 73A3621A5DB4EDBF660C671792E13759 /* GTMGatherInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMGatherInputStream.m; path = Source/GTMGatherInputStream.m; sourceTree = ""; }; + 73A677A14C9FC931B5AD7E2C51F74A91 /* FImmutableSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m; sourceTree = ""; }; + 73C7F092D26BAFEA89D9BDF33EA12285 /* es-SV.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-SV.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-SV.lproj"; sourceTree = ""; }; + 73DDA3AD22CD6A161783A626C136DA24 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 742472618BFECC201CA07F8853313A60 /* log_writer.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_writer.cc; path = db/log_writer.cc; sourceTree = ""; }; + 74A271C15E69BBCEC463F5F670300BA1 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 74A4644D82340D84377819E6EFA115CC /* es-DO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-DO.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-DO.lproj"; sourceTree = ""; }; + 74FF9CA663893AB6239A094AAAAEA2C8 /* FIRGetProjectConfigRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetProjectConfigRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigRequest.h; sourceTree = ""; }; + 752204D20D33393B7F9DFE09AC0A6117 /* pt-PT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "pt-PT.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/pt-PT.lproj"; sourceTree = ""; }; + 7553C3CCF22589D84A1833B82BD7B112 /* GTMSessionUploadFetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionUploadFetcher.h; path = Source/GTMSessionUploadFetcher.h; sourceTree = ""; }; + 757AFA09EEDF7E69BA225B0049AE4C79 /* FIRDeleteAccountRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDeleteAccountRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.m; sourceTree = ""; }; + 75C5467758DF25A71712616698EFBF6C /* PromisesObjC-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "PromisesObjC-Info.plist"; sourceTree = ""; }; + 75E656E2ACA0B8C607F571F7D16128A5 /* OIDErrorUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDErrorUtilities.h; path = Source/AppAuthCore/OIDErrorUtilities.h; sourceTree = ""; }; + 75FAA3E93E73C340192C7B4B9471389B /* FIRAuthProtoMFAEnrollment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProtoMFAEnrollment.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.h; sourceTree = ""; }; + 762FA9EE5DB6C426EB4469042AC1AF92 /* OIDAuthorizationResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthorizationResponse.h; path = Source/AppAuthCore/OIDAuthorizationResponse.h; sourceTree = ""; }; + 764B12FF08FBAAAC81693F5927AEABED /* FIRStorageUpdateMetadataTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUpdateMetadataTask.h; path = FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h; sourceTree = ""; }; + 76514376A644F1C0AAD24B289F8F5F35 /* FUIGoogleAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIGoogleAuth.h; path = GoogleAuth/FirebaseGoogleAuthUI/FUIGoogleAuth.h; sourceTree = ""; }; + 76653C0C50EDD5D4C16513CE8BEEC454 /* FIRUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUser.h; path = FirebaseAuth/Sources/Public/FIRUser.h; sourceTree = ""; }; + 766A6826F51D60F3F8BF5907E443E340 /* GDTCOREvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h; sourceTree = ""; }; + 76A00F380F7CB86BC5ABAB18B8C3C512 /* es-NI.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-NI.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-NI.lproj"; sourceTree = ""; }; + 76C1B4F4BBB24C931633B0FBBA0B87F5 /* FIRInstallationsStoredAuthToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredAuthToken.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h; sourceTree = ""; }; + 76C1B95C2C3697B27A7E6D35B1471E75 /* FIRStorageDeleteTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageDeleteTask.m; path = FirebaseStorage/Sources/FIRStorageDeleteTask.m; sourceTree = ""; }; + 76C514358FDBBCF9A559BE493725B973 /* en-GB.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-GB.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-GB.lproj"; sourceTree = ""; }; + 76E51504F5FFB6652AFD71EF86591B2A /* ja.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ja.lproj; path = Auth/FirebaseAuthUI/Strings/ja.lproj; sourceTree = ""; }; + 76F463D2321280A211075F635EB82633 /* FTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTree.h; path = Firebase/Database/Core/Utilities/FTree.h; sourceTree = ""; }; + 76F71A018847DEC561975C4EADA9A9F6 /* FIRInstallationsItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsItem.h; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.h; sourceTree = ""; }; + 7705D67F509F485AE9F635CEFF68D4FC /* FIRAuthExceptionUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthExceptionUtils.h; path = FirebaseAuth/Sources/Utilities/FIRAuthExceptionUtils.h; sourceTree = ""; }; + 77428BF49AAD71B811C8A6049C09E441 /* zh.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = zh.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/zh.lproj; sourceTree = ""; }; + 775B864B453C9AE0D8B96507F09A9F80 /* FIREmailAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIREmailAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/Email/FIREmailAuthProvider.m; sourceTree = ""; }; + 778802077ADDAF4B7A52B59847FE54DB /* es-PY.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PY.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-PY.lproj"; sourceTree = ""; }; + 77AC5C0D1A2EAB140E1050E088AAC8AA /* FIRFinalizeMFAEnrollmentResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFinalizeMFAEnrollmentResponse.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.m; sourceTree = ""; }; + 77AFF048E9D11813E82960D3522E228C /* ca.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ca.lproj; path = Auth/FirebaseAuthUI/Strings/ca.lproj; sourceTree = ""; }; + 77CA828E70063B77546CDEF7F69497FF /* OIDScopeUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDScopeUtilities.h; path = Source/AppAuthCore/OIDScopeUtilities.h; sourceTree = ""; }; + 77EC7724051F1C393F7400C9463218FA /* es-MX.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-MX.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-MX.lproj"; sourceTree = ""; }; + 782C0B18B8A79A056DC2C87331FC21DC /* GULAppDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppDelegateSwizzler.m; path = GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m; sourceTree = ""; }; + 7853F03B091136CF9515F12807177703 /* FIRWithdrawMFAResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRWithdrawMFAResponse.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.m; sourceTree = ""; }; + 787252786CD85DC82A24166F78BD4E85 /* port_example.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_example.h; path = port/port_example.h; sourceTree = ""; }; + 78A548A17202BBEBCAD3914415FA6185 /* hi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hi.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/hi.lproj; sourceTree = ""; }; + 78A9978BE5C233D164CD7C226805A2D0 /* FIRDatabaseReference.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseReference.m; path = Firebase/Database/FIRDatabaseReference.m; sourceTree = ""; }; + 78AB14E26E13BE6E71FA466FD1F7C0FC /* FIRMultiFactorSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactorSession.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession.m; sourceTree = ""; }; + 78DA4E0D7190329C4F87CE06689EF217 /* FirebaseDatabase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseDatabase.debug.xcconfig; sourceTree = ""; }; + 78DB579CADEFEB232525FF20715796F3 /* GULApplication.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULApplication.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h; sourceTree = ""; }; + 78E128753A283DBACD262E6F97C1D738 /* it.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = it.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/it.lproj; sourceTree = ""; }; + 78E779BCE9ACE526BBCA1D359975D546 /* iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = iterator.cc; path = table/iterator.cc; sourceTree = ""; }; + 792379C88F502528FDFCFE6202E0702E /* GTMReadMonitorInputStream.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMReadMonitorInputStream.m; path = Source/GTMReadMonitorInputStream.m; sourceTree = ""; }; + 792D76D6241F70B08F7CAD7ADB1D72E2 /* pb_decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_decode.h; sourceTree = ""; }; + 7941AC0839A2D5B716F6C262BA452CF0 /* GDTCORReachability.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORReachability.h; sourceTree = ""; }; + 795CBFB69FAF7FD49AC3054E91F5ED2A /* cct.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cct.nanopb.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h; sourceTree = ""; }; + 796D52C9F909C41144190320EC3D42ED /* sr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sr.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/sr.lproj; sourceTree = ""; }; + 79A12CF03274F6EAB14327C8ADDDC0DA /* el.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = el.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/el.lproj; sourceTree = ""; }; + 79A25A30BCAF35ADC592EE18444941D9 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + 79C0C49B9FD1D38A300F17C741E09F97 /* FIROAuthCredential_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROAuthCredential_Internal.h; path = FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h; sourceTree = ""; }; + 79DC4E4C9D18B8167EC254230731F98F /* FIRBundleUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRBundleUtil.h; path = FirebaseCore/Sources/FIRBundleUtil.h; sourceTree = ""; }; + 7A8163F1A18B941E2293A680A78F8EBC /* FArraySortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FArraySortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h; sourceTree = ""; }; + 7AAD146A75E91278F8462790889BE1D3 /* GTMAppAuth-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMAppAuth-umbrella.h"; sourceTree = ""; }; + 7ABD2BED9DB9379A85F50B0F047351FC /* FAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAuthTokenProvider.m; path = Firebase/Database/Login/FAuthTokenProvider.m; sourceTree = ""; }; + 7B05C4EB3F8989AA897BCBBBC215D6AA /* GoogleUtilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleUtilities-dummy.m"; sourceTree = ""; }; + 7B0AD5E6656068EFD990FF19F45F0202 /* FIRStorageConstants_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageConstants_Private.h; path = FirebaseStorage/Sources/FIRStorageConstants_Private.h; sourceTree = ""; }; + 7BA768461B023567D35A1231C542EC87 /* FIRInstallationsIDController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIDController.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m; sourceTree = ""; }; + 7BCE6DCCBAC25268B5B31598C195FF5C /* FIRCreateAuthURIRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCreateAuthURIRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.m; sourceTree = ""; }; + 7C2013D50092AC3FF5988D10C0269AC9 /* es-DO.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-DO.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-DO.lproj"; sourceTree = ""; }; + 7C3645F8ACEB96B24FFEE072C49B858A /* FUIAuthUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthUtils.m; path = Auth/FirebaseAuthUI/FUIAuthUtils.m; sourceTree = ""; }; + 7C3D34F30D5AC628C0E88C3FDE526588 /* FLevelDBStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLevelDBStorageEngine.h; path = Firebase/Database/Persistence/FLevelDBStorageEngine.h; sourceTree = ""; }; + 7C6EF5A4DB9F566411010DC8177A31C8 /* FIRGoogleAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGoogleAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthProvider.m; sourceTree = ""; }; + 7C73C0921C9BCBB67271CD840F1E8552 /* FLLRBNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h; sourceTree = ""; }; + 7CA5F3D7DC34FE7C993F9CDB4D26F4DD /* logging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = logging.h; path = util/logging.h; sourceTree = ""; }; + 7CA87D9C42EE5FB93F71C78E42F2D2EF /* ic_visibility_off@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_visibility_off@3x.png"; path = "Auth/FirebaseAuthUI/Resources/ic_visibility_off@3x.png"; sourceTree = ""; }; + 7D08AD02B34E13ED754D40A419127430 /* FCancelEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCancelEvent.h; path = Firebase/Database/Core/View/FCancelEvent.h; sourceTree = ""; }; + 7D1C0142C1B858F367068429A25E9A45 /* arena.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = arena.cc; path = util/arena.cc; sourceTree = ""; }; + 7D89B61F748E61F84C2D14454827CD41 /* FIRAuthURLPresenter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthURLPresenter.m; path = FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.m; sourceTree = ""; }; + 7DD45737EBC43DFABAA9FF8C8070FFA8 /* Pods-MyExperiences-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-MyExperiences-acknowledgements.plist"; sourceTree = ""; }; + 7E0A008BCE52F3A0574E15041D57A2CC /* FViewProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessor.h; path = Firebase/Database/FViewProcessor.h; sourceTree = ""; }; + 7EB1396AABC1139BB96C6491579BD8F4 /* FView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FView.m; path = Firebase/Database/Core/View/FView.m; sourceTree = ""; }; + 7EB6C4F707D6AE247061BDE99F5582DF /* comparator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = comparator.h; path = include/leveldb/comparator.h; sourceTree = ""; }; + 7EBE8D30CFE961F27D4DCEF388590C8C /* c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = c.cc; path = db/c.cc; sourceTree = ""; }; + 7ED5B5B260DA1124ED4F9279DD4FCC12 /* FIRStartMFAEnrollmentRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStartMFAEnrollmentRequest.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.h; sourceTree = ""; }; + 7EE4774B8121D656C797F2900CD8BDBE /* FIRAuthNotificationManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthNotificationManager.h; path = FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.h; sourceTree = ""; }; + 7F0A65267EACC1715344BFD364530CF2 /* FIRAuthErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthErrors.h; path = FirebaseAuth/Sources/Public/FIRAuthErrors.h; sourceTree = ""; }; + 7F5524306327B8BA3131DB42B97A17CD /* FirebaseCoreDiagnostics-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCoreDiagnostics-dummy.m"; sourceTree = ""; }; + 7F6F1EC69708D5FC3C78D21BD2150788 /* Pods-MyExperiences.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-MyExperiences.debug.xcconfig"; sourceTree = ""; }; + 7F78C92980B846317529AEE3CAF792AA /* FTupleRemovedQueriesEvents.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleRemovedQueriesEvents.h; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h; sourceTree = ""; }; + 7F9AF4AD8155223C8FEEE6032B169F66 /* sl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sl.lproj; path = Auth/FirebaseAuthUI/Strings/sl.lproj; sourceTree = ""; }; + 7FAD4119D663241EA3AEADF1D7CE00C5 /* pl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = pl.lproj; path = Auth/FirebaseAuthUI/Strings/pl.lproj; sourceTree = ""; }; + 7FE12394BAF5BCDF91A1683D1D50C8DC /* ar.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ar.lproj; path = Auth/FirebaseAuthUI/Strings/ar.lproj; sourceTree = ""; }; + 80555E26FEBB765547F06A92F10BBFAC /* ic_account_circle2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_account_circle2x.png; path = Auth/FirebaseAuthUI/Resources/ic_account_circle2x.png; sourceTree = ""; }; + 80582A0611F09855A38F9572F5DAAFBE /* ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist"; sourceTree = ""; }; + 8075BDC5128A59A8A356556917442DC7 /* FIRSignInWithGameCenterResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSignInWithGameCenterResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.m; sourceTree = ""; }; + 809049EFAF08B2C4551CFB733542CEA5 /* FirebaseCoreDiagnostics.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCoreDiagnostics.modulemap; sourceTree = ""; }; + 80E00FBA13DD98479E065206F43AB591 /* lt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = lt.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/lt.lproj; sourceTree = ""; }; + 810D84765A63AC3EFC5E3C943E7597E3 /* GTMKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMKeychain.h; path = Source/GTMKeychain.h; sourceTree = ""; }; + 813EE38656EDBC2CE28989B9B8E3D86F /* GTMAppAuth.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GTMAppAuth.debug.xcconfig; sourceTree = ""; }; + 818E56D83F281D68C11461EBA7312C1E /* FBLPromise+Testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Testing.h"; path = "Sources/FBLPromises/include/FBLPromise+Testing.h"; sourceTree = ""; }; + 81947381D2EAFE5DAE6EB80D863358BD /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + 81B6701477B6C985CE39D787B599F110 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + 82048231EF2E3884801064A817757265 /* format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = format.h; path = table/format.h; sourceTree = ""; }; + 823FF738D2EDB86AD387E9C9A0628A1F /* FBLPromisePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromisePrivate.h; path = Sources/FBLPromises/include/FBLPromisePrivate.h; sourceTree = ""; }; + 82C7731D87C6760CDF18BCA19341307A /* FIRUserInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUserInfo.h; path = FirebaseAuth/Sources/Public/FIRUserInfo.h; sourceTree = ""; }; + 82FB7E4D042D8701D3495BC636CF8FAC /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + 838C87E3EEC318432FFA15251F58F8F9 /* FTupleStringNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleStringNode.m; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.m; sourceTree = ""; }; + 83B54EDA0B44A3B61BA9E8304A43868A /* GDTCORTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransformer.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m; sourceTree = ""; }; + 843D31A14C08E44DE861EC9068CF935A /* FIREmailLinkSignInRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIREmailLinkSignInRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.m; sourceTree = ""; }; + 8458CF3753249A59F6F220A43276CADE /* sr-Latn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "sr-Latn.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/sr-Latn.lproj"; sourceTree = ""; }; + 8469477C787E65AC4DECFB61629C330F /* FListenComplete.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenComplete.m; path = Firebase/Database/FListenComplete.m; sourceTree = ""; }; + 846FC1E466FBFE0D850CD2366D07FD41 /* FIRMultiFactor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactor.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactor.m; sourceTree = ""; }; + 847467AF5025D6B485DB432C7B7581C2 /* FEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEvent.h; path = Firebase/Database/Core/View/FEvent.h; sourceTree = ""; }; + 84B17AAF40781DB944D8E2218CE3D551 /* FIRSecureTokenRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSecureTokenRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenRequest.h; sourceTree = ""; }; + 84B8016FA7491959E6CEBA3C1A3E0E22 /* GDTCORTransport_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h; sourceTree = ""; }; + 84DBFD500F6079D0B3DE7D70BF750C3A /* GULSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSwizzler.h; path = GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h; sourceTree = ""; }; + 855CE6FFCB03AA76B086DD233B1F03BE /* hash.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = hash.cc; path = util/hash.cc; sourceTree = ""; }; + 855E8833CCE10619B411301B970C1A9F /* dbformat.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dbformat.cc; path = db/dbformat.cc; sourceTree = ""; }; + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransport.framework; path = GoogleDataTransport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 858E389F4C5941E87CE495D9F4C3F1D5 /* GDTCCTCompressionHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTCompressionHelper.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m; sourceTree = ""; }; + 85963F5A5D4793A9C69D9C6A48407761 /* FIRStorageUploadTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUploadTask.m; path = FirebaseStorage/Sources/FIRStorageUploadTask.m; sourceTree = ""; }; + 85CEC317B81F1610CC32F5A36302B5EB /* ic_account_circle3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_account_circle3x.png; path = Auth/FirebaseAuthUI/Resources/ic_account_circle3x.png; sourceTree = ""; }; + 85F1F6036F7E1CBEF9C35C3689DE4CAE /* FRepoManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoManager.m; path = Firebase/Database/Core/FRepoManager.m; sourceTree = ""; }; + 861BCD20A2A3B56F580C7A5CA766DF8C /* FIRInstallationsItem+RegisterInstallationAPI.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstallationsItem+RegisterInstallationAPI.m"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m"; sourceTree = ""; }; + 8652F37C3DC08512EA394530E2F59BC8 /* FIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndex.h; path = Firebase/Database/FIndex.h; sourceTree = ""; }; + 865D3B59B3F895B75DB12A7B67131BB3 /* FSnapshotUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotUtilities.h; path = Firebase/Database/Snapshot/FSnapshotUtilities.h; sourceTree = ""; }; + 866CC51076A49B7A5196DCF601092E13 /* FTupleBoolBlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleBoolBlock.h; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h; sourceTree = ""; }; + 86785462374CEE6C2A26DF27723AFD08 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + 868E02358BA6AC33B570F4302DD9FE18 /* zh-Hant-TW.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant-TW.lproj"; path = "Auth/FirebaseAuthUI/Strings/zh-Hant-TW.lproj"; sourceTree = ""; }; + 86A61AF98CFC730742F2497D6BD3094C /* coding.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = coding.cc; path = util/coding.cc; sourceTree = ""; }; + 86FBE6D4358D22E5A6431DB64E093622 /* GULNetworkConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkConstants.m; path = GoogleUtilities/Network/GULNetworkConstants.m; sourceTree = ""; }; + 87174475F1969D1150949EC200E43A9E /* FUIAccountSettingsOperationUnlinkAccount.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationUnlinkAccount.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.h; sourceTree = ""; }; + 875E1AF5B72E29DF5D842CD418D664AC /* FIRMultiFactorResolver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactorResolver.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactorResolver.m; sourceTree = ""; }; + 8790E43ACFD7A0F4E4F20D3DE7E249B5 /* FTupleBoolBlock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleBoolBlock.m; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m; sourceTree = ""; }; + 87AE5F696B5814E7D5E782404086EC91 /* FirebaseInstallations-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstallations-Info.plist"; sourceTree = ""; }; + 8810AE5E10E7D7E8DB0D9B3CB32C0D9B /* FTransformedEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTransformedEnumerator.m; path = Firebase/Database/FTransformedEnumerator.m; sourceTree = ""; }; + 88D1A747FD5261ACFF61437E691C185B /* FUIAuthPickerViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIAuthPickerViewController.xib; path = Auth/FirebaseAuthUI/FUIAuthPickerViewController.xib; sourceTree = ""; }; + 89891420777E264E545EE3102D324C80 /* GDTCORPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPrioritizer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h; sourceTree = ""; }; + 8A44D696F2163787D7CA8EF6B66B3B29 /* fbase64.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fbase64.c; path = Firebase/Database/third_party/SocketRocket/fbase64.c; sourceTree = ""; }; + 8A48AB5E3FB50C36BA0EC0B20B809C21 /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 8AA74947BFD3B18B07530AB29E37CB2B /* es-PR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PR.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PR.lproj"; sourceTree = ""; }; + 8ACC5CF4825F2AD7C86F0B0739E82CC7 /* FIRInstallationsAuthTokenResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResult.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h; sourceTree = ""; }; + 8AD08C35B5ACC18737C7E17D782539A9 /* GULReachabilityChecker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULReachabilityChecker.m; path = GoogleUtilities/Reachability/GULReachabilityChecker.m; sourceTree = ""; }; + 8AEE4F8D71B44E0B56E0871B80A32DEC /* FIRMutableData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMutableData.m; path = Firebase/Database/Api/FIRMutableData.m; sourceTree = ""; }; + 8AF57F015004BABC4B46244296756737 /* dumpfile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dumpfile.h; path = include/leveldb/dumpfile.h; sourceTree = ""; }; + 8BB9C5BE4514F02342045406DF9624D8 /* OIDResponseTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDResponseTypes.m; path = Source/AppAuthCore/OIDResponseTypes.m; sourceTree = ""; }; + 8BE1FBFA703800A2B83E044EE565A1A6 /* ln.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ln.lproj; path = Auth/FirebaseAuthUI/Strings/ln.lproj; sourceTree = ""; }; + 8BF46F360C12AAC644A4E6A1F433F683 /* FStringUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FStringUtilities.m; path = Firebase/Database/Utilities/FStringUtilities.m; sourceTree = ""; }; + 8BFC8863CD88E6BCE4F75A47B49C31FA /* GTMSessionFetcher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GTMSessionFetcher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8BFD29E8171D39915525EB07724F0AEB /* FIRGetAccountInfoRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetAccountInfoRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.h; sourceTree = ""; }; + 8C3177C16671C84C8825F706F9F17A4E /* GULNetwork.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetwork.m; path = GoogleUtilities/Network/GULNetwork.m; sourceTree = ""; }; + 8C387865C9997476DD5F58576360815E /* OIDTokenUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDTokenUtilities.h; path = Source/AppAuthCore/OIDTokenUtilities.h; sourceTree = ""; }; + 8C76C26999C5EBBF7EA157465C0939D5 /* FStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStorageEngine.h; path = Firebase/Database/Persistence/FStorageEngine.h; sourceTree = ""; }; + 8C8947AB7BD466CCB237F6F4D68045B0 /* FIRStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorage.h; path = FirebaseStorage/Sources/Public/FIRStorage.h; sourceTree = ""; }; + 8C9DAD4624BF9ACE5C50723DE347FA8F /* FIRGameCenterAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGameCenterAuthCredential.h; path = FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h; sourceTree = ""; }; + 8CAB24B3E0499D3AEFE0BB09F8A193D5 /* nanopb-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "nanopb-Info.plist"; sourceTree = ""; }; + 8CC90D6F4005C5FBF64F12F2C50BA755 /* FirebaseDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseDatabase.h; path = Firebase/Database/Public/FirebaseDatabase.h; sourceTree = ""; }; + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCoreDiagnostics.framework; path = FirebaseCoreDiagnostics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CFBC168B85EA71F74E6C24C03FDCA9D /* FIRStorageObservableTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageObservableTask.h; path = FirebaseStorage/Sources/Public/FIRStorageObservableTask.h; sourceTree = ""; }; + 8D1522D9A59FBC064607570F12367743 /* GoogleDataTransportCCTSupport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransportCCTSupport-umbrella.h"; sourceTree = ""; }; + 8D643088290FC363A90F847070973A68 /* FParsedUrl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FParsedUrl.h; path = Firebase/Database/Utilities/FParsedUrl.h; sourceTree = ""; }; + 8DBA967F5DF73F8FE98398812A2958BF /* FIRLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLoggerLevel.h; path = FirebaseCore/Sources/Public/FIRLoggerLevel.h; sourceTree = ""; }; + 8E3007F6BD5E438E138650DDACCAA423 /* FIRAuth_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuth_Internal.h; path = FirebaseAuth/Sources/Auth/FIRAuth_Internal.h; sourceTree = ""; }; + 8EAB0E19E6BFAE72A24B17CDAE58272E /* ur.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ur.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ur.lproj; sourceTree = ""; }; + 8ED22E829FF20FF3C96668710289B582 /* FIRApp.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRApp.m; path = FirebaseCore/Sources/FIRApp.m; sourceTree = ""; }; + 8EE688B7F2552F591256057AE7161815 /* FIRMultiFactor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMultiFactor.h; path = FirebaseAuth/Sources/Public/FIRMultiFactor.h; sourceTree = ""; }; + 8EEC83A35CA914EF24F3A4863B5C2EA9 /* FIRVerifyCustomTokenResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyCustomTokenResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenResponse.m; sourceTree = ""; }; + 8F7D6DB45BC5F0FC8039D5B4B9655B28 /* GDTCOREventTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h; sourceTree = ""; }; + 8FA5000DD7FFCB9CB4D8C8E26F0B142F /* ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist"; sourceTree = ""; }; + 8FB936E76A9A8C28FD4C57098BA48A88 /* OIDServiceDiscovery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDServiceDiscovery.h; path = Source/AppAuthCore/OIDServiceDiscovery.h; sourceTree = ""; }; + 9003091EE6B741989C260584A1A67492 /* FIRAuthKeychainServices.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthKeychainServices.h; path = FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.h; sourceTree = ""; }; + 900D7AA1AF5F2CCCFEC7B2A6D7F92D3B /* FIRAdditionalUserInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAdditionalUserInfo.m; path = FirebaseAuth/Sources/User/FIRAdditionalUserInfo.m; sourceTree = ""; }; + 904ACA95784DB45F51C8EA34D83966A8 /* ko.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ko.lproj; path = Auth/FirebaseAuthUI/Strings/ko.lproj; sourceTree = ""; }; + 907BBDD52C7ED77CC879E7EA2FF71132 /* FView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FView.h; path = Firebase/Database/Core/View/FView.h; sourceTree = ""; }; + 90EF156F21BA67E590DD858B42B6D67E /* pt-PT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "pt-PT.lproj"; path = "Auth/FirebaseAuthUI/Strings/pt-PT.lproj"; sourceTree = ""; }; + 9116AE55C96DD4B7CC8A610D2763F4CC /* FIRSecureTokenResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSecureTokenResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.m; sourceTree = ""; }; + 91200D0F48E695F4F2B5024B2FAA9F80 /* FIROAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential.m; sourceTree = ""; }; + 912B58F48447E074A2D77B3BDB573ABE /* FIRServerValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRServerValue.m; path = Firebase/Database/Api/FIRServerValue.m; sourceTree = ""; }; + 917C3FA5633CF0BC4302E35ED0133084 /* FListenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenProvider.h; path = Firebase/Database/Core/FListenProvider.h; sourceTree = ""; }; + 9237CE067B92CC661714D1430998DA2D /* FTrackedQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQuery.m; path = Firebase/Database/Persistence/FTrackedQuery.m; sourceTree = ""; }; + 924E549ABA7E7BBBCFAC5E46CA17885C /* OIDExternalUserAgentSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentSession.h; path = Source/AppAuthCore/OIDExternalUserAgentSession.h; sourceTree = ""; }; + 925C41F8B9D85ABE6F2C5D11D6784234 /* FBLPromise+Then.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Then.h"; path = "Sources/FBLPromises/include/FBLPromise+Then.h"; sourceTree = ""; }; + 9263934336E5BCC5C8C49D503E09B471 /* FIRAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuth.h; path = FirebaseAuth/Sources/Public/FIRAuth.h; sourceTree = ""; }; + 92F0DCFFD953EC71FCFDB3666D6EA0F4 /* FirebaseAuth-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseAuth-dummy.m"; sourceTree = ""; }; + 93350B3059FFA3016BE438DE54C68169 /* FQuerySpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQuerySpec.m; path = Firebase/Database/Core/FQuerySpec.m; sourceTree = ""; }; + 9355EE8CB9035164A79720BFC33A56ED /* FirebaseStorage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseStorage-umbrella.h"; sourceTree = ""; }; + 9374F6D4F9703C1046AF6A58B1D1F189 /* FIROAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROAuthCredential.h; path = FirebaseAuth/Sources/Public/FIROAuthCredential.h; sourceTree = ""; }; + 93E345CDC9AD0E97100D7EB33EC1D156 /* FirebaseUI-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseUI-prefix.pch"; sourceTree = ""; }; + 93F4E2727B989CA69B54F7395BCF5716 /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + 94186DE3D7783AF3D30A3B3D37ABB931 /* FSnapshotHolder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotHolder.m; path = Firebase/Database/Core/FSnapshotHolder.m; sourceTree = ""; }; + 945357ECAD83195AA46CE7BEE8C52071 /* ta.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ta.lproj; path = Auth/FirebaseAuthUI/Strings/ta.lproj; sourceTree = ""; }; + 95171A26BA94A2DC6A9774AFE265085B /* FLLRBEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBEmptyNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h; sourceTree = ""; }; + 9532DBD2E25AE8B4F16B588047B3C540 /* FIRSignUpNewUserResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSignUpNewUserResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h; sourceTree = ""; }; + 953494A16560D8217BD92077C174DEA4 /* FUIAuthBaseViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthBaseViewController.m; path = Auth/FirebaseAuthUI/FUIAuthBaseViewController.m; sourceTree = ""; }; + 953C2D3F948748A2BD8EA7A019A49819 /* FIRComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponent.m; path = FirebaseCore/Sources/FIRComponent.m; sourceTree = ""; }; + 95D34077E7127C594A944B755B63D902 /* FIRMultiFactorInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMultiFactorInfo.m; path = FirebaseAuth/Sources/MultiFactor/FIRMultiFactorInfo.m; sourceTree = ""; }; + 95FA9C91714169BCFFD60B45C1E46863 /* AppAuth-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AppAuth-umbrella.h"; sourceTree = ""; }; + 960C38CE31171CABDBD3DCD719DC79DF /* env_posix.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env_posix.cc; path = util/env_posix.cc; sourceTree = ""; }; + 96164D8ACC099570AEFE2AD13C866D21 /* FIRAnalyticsConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsConfiguration.h; path = FirebaseCore/Sources/FIRAnalyticsConfiguration.h; sourceTree = ""; }; + 961B225F52CE4624C6901942FBDA468A /* nanopb.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = nanopb.modulemap; sourceTree = ""; }; + 9646F23A0D4521DB88A49AE6ABD164D8 /* GDTCORClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORClock.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORClock.m; sourceTree = ""; }; + 964A6F832C7C75A9B0A0FB580C10E821 /* FTreeSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m; sourceTree = ""; }; + 96F59E405A529746B24F54B8A9CA58FA /* FIRAnalyticsConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAnalyticsConfiguration.m; path = FirebaseCore/Sources/FIRAnalyticsConfiguration.m; sourceTree = ""; }; + 96FD8C25F5D68FCD5169FC2E6D0B9C50 /* port.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port.h; path = port/port.h; sourceTree = ""; }; + 97031F647363FF54D7E0D14B833CB369 /* en-IN.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-IN.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IN.lproj"; sourceTree = ""; }; + 972070C5155A5F1E91B6A9DB11D2258B /* FIRSendVerificationCodeRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSendVerificationCodeRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.h; sourceTree = ""; }; + 978D9CD5FC2DD944D7B8A6F1FA1332CA /* FirebaseUI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseUI.modulemap; sourceTree = ""; }; + 979EE14740E14EBC7F7EC39F2D7B7574 /* FIRPhoneAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRPhoneAuthProvider.h; sourceTree = ""; }; + 97B15D8306560971C11A226391C02BBD /* FIRStartMFASignInRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStartMFASignInRequest.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.h; sourceTree = ""; }; + 984741AB13FDFAE0FBB3AEADA04EDBBE /* FirebaseCoreInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCoreInternal.h; path = FirebaseCore/Sources/Private/FirebaseCoreInternal.h; sourceTree = ""; }; + 98C64CF03F4D64D5309F6FFA11432FED /* GTMMIMEDocument.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMMIMEDocument.h; path = Source/GTMMIMEDocument.h; sourceTree = ""; }; + 98E076D44BAA2867EABD71555B9ADF26 /* FIRCoreDiagnostics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnostics.m; path = Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m; sourceTree = ""; }; + 98E737E02BDF5544C7E4CCC8C2207DBC /* FirebaseDatabase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseDatabase.modulemap; sourceTree = ""; }; + 993295ECC4A249DC7D75827B7832BFAF /* FIRAuthKeychainServices.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthKeychainServices.m; path = FirebaseAuth/Sources/Storage/FIRAuthKeychainServices.m; sourceTree = ""; }; + 9965D14C5646EB689F1143289D36CDB5 /* FUIAuthErrorUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthErrorUtils.h; path = Auth/FirebaseAuthUI/FUIAuthErrorUtils.h; sourceTree = ""; }; + 99974DDC351C326D0E6D04F23686DD5A /* OIDTokenUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDTokenUtilities.m; path = Source/AppAuthCore/OIDTokenUtilities.m; sourceTree = ""; }; + 99BF294419A82872B273C32B3313AD54 /* de-CH.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "de-CH.lproj"; path = "Auth/FirebaseAuthUI/Strings/de-CH.lproj"; sourceTree = ""; }; + 99E2BC6EBB91C9FFC6F7A11D13DC86AB /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 9A23A0C9B7AC4E516824E1155565BF31 /* mr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = mr.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/mr.lproj; sourceTree = ""; }; + 9AB447E9106C479163FEB96B7765FE05 /* FIRVerifyAssertionRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyAssertionRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.m; sourceTree = ""; }; + 9AD952A817926DC83697902428396A10 /* GoogleUtilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-prefix.pch"; sourceTree = ""; }; + 9B18A4515BDC97476AC776D94BEC8918 /* FIRPhoneAuthCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneAuthCredential.h; path = FirebaseAuth/Sources/Public/FIRPhoneAuthCredential.h; sourceTree = ""; }; + 9B232AAF44021458D2D8894666F9EB80 /* FirebaseStorage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseStorage-Info.plist"; sourceTree = ""; }; + 9B54C1685D4AACE5220DAA13C8DAF23A /* FUIAccountSettingsOperationForgotPassword.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationForgotPassword.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationForgotPassword.h; sourceTree = ""; }; + 9B5DAA4FAAD2341569C841186C84AB46 /* lt.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = lt.lproj; path = Auth/FirebaseAuthUI/Strings/lt.lproj; sourceTree = ""; }; + 9B88966B5383F85545E1AAFBB02C4726 /* leveldb-library-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-prefix.pch"; sourceTree = ""; }; + 9B9627E22602C602EF52BFF49FE56D98 /* FValueIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueIndex.m; path = Firebase/Database/FValueIndex.m; sourceTree = ""; }; + 9C11205E4D4588C7ABA50978488F6849 /* zh-Hans.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hans.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hans.lproj"; sourceTree = ""; }; + 9C199C6C880F5BBB8AC4A31DBDFD42AE /* FIRSetAccountInfoResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSetAccountInfoResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h; sourceTree = ""; }; + 9C323A9CB167C308F134470280417C15 /* Pods-MyExperiences-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-MyExperiences-frameworks.sh"; sourceTree = ""; }; + 9C5E6C966427FB61A02E3C1DA552D236 /* FIRStorageGetDownloadURLTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetDownloadURLTask.h; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h; sourceTree = ""; }; + 9C6715856AC895328A2AEAFC8B86E640 /* FTupleTSN.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTSN.m; path = Firebase/Database/Utilities/Tuples/FTupleTSN.m; sourceTree = ""; }; + 9C74A51246137BE63D7AD4A74D0FD7D9 /* FUIAccountSettingsOperation_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperation_Internal.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation_Internal.h; sourceTree = ""; }; + 9C75CA0EA947F458A55BC7558B99C325 /* GDTCCTCompressionHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTCompressionHelper.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h; sourceTree = ""; }; + 9C8CF2EC8254BD9488FC31DE753FDE52 /* memtable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = memtable.h; path = db/memtable.h; sourceTree = ""; }; + 9C927FF92EAEBC5B576C5C5ACD1BFA00 /* GDTCORTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h; sourceTree = ""; }; + 9C95D1C7C8FCD7CAF183BC0E158F01C7 /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + 9CA4F38D6112A713AD3F9140E7F68026 /* FUIStaticContentTableViewManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIStaticContentTableViewManager.h; path = Auth/FirebaseAuthUI/FUIStaticContentTableViewManager.h; sourceTree = ""; }; + 9CD80825846CFECCE10B535583137409 /* FEventRaiser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRaiser.h; path = Firebase/Database/Core/View/FEventRaiser.h; sourceTree = ""; }; + 9CEA234D8D45743863BF4E8BDB6ECA14 /* FIRConfigurationInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfigurationInternal.h; path = FirebaseCore/Sources/FIRConfigurationInternal.h; sourceTree = ""; }; + 9CED810C143F8723E760A6F7C2DA34C2 /* en-ZA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-ZA.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-ZA.lproj"; sourceTree = ""; }; + 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseStorage.framework; path = FirebaseStorage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D19FDA9CE8895E11678DDCB7526EF93 /* GoogleAppMeasurement.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.debug.xcconfig; sourceTree = ""; }; + 9D1C280352A1F5631E02957E16C08DD7 /* FIRWithdrawMFAResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRWithdrawMFAResponse.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFAResponse.h; sourceTree = ""; }; + 9D340BECB137147E09B0C0BDB14FCC42 /* en-SG.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-SG.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-SG.lproj"; sourceTree = ""; }; + 9D3C88BA14651AAF531A1534E6274A7D /* FIRAuthSerialTaskQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthSerialTaskQueue.h; path = FirebaseAuth/Sources/Auth/FIRAuthSerialTaskQueue.h; sourceTree = ""; }; + 9D469034D09270D26A090BD73BAF7BBB /* FIRAuthAppCredentialManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthAppCredentialManager.m; path = FirebaseAuth/Sources/SystemService/FIRAuthAppCredentialManager.m; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9DF71716C207DAB7D4A96B5EC78F76FE /* OIDTokenRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDTokenRequest.h; path = Source/AppAuthCore/OIDTokenRequest.h; sourceTree = ""; }; + 9E8E8A2ED064D9D1ADB6E5DEBAD99AB7 /* FLLRBValueNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBValueNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m; sourceTree = ""; }; + 9EA4E84EC07EDEE7CEB2CF5CB07768D0 /* FBLPromise+Validate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Validate.h"; path = "Sources/FBLPromises/include/FBLPromise+Validate.h"; sourceTree = ""; }; + 9EEA4E41181C12F276CA21332BF193E0 /* GULAppDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler_Private.h; path = GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h; sourceTree = ""; }; + 9EF93A47B978CDA02A82640CB31708FF /* thread_annotations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = thread_annotations.h; path = port/thread_annotations.h; sourceTree = ""; }; + 9F19F2DAB2BE2733FD82D447F48A654C /* fr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fr.lproj; path = Auth/FirebaseAuthUI/Strings/fr.lproj; sourceTree = ""; }; + 9F27A7A83BC933E0BA0CF7DD8D4E4C81 /* FViewProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessor.m; path = Firebase/Database/FViewProcessor.m; sourceTree = ""; }; + 9F36BCB3D0BD01DDB626C5FE3F73DFBE /* NSData+SRB64Additions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+SRB64Additions.m"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m"; sourceTree = ""; }; + 9F4106304CD7FCBAC9D6A0DCB765AA54 /* FIRInstallationsItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsItem.m; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.m; sourceTree = ""; }; + 9F6B023A8F096B22FC186C9C8E59C42A /* nanopb-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "nanopb-dummy.m"; sourceTree = ""; }; + 9F70E4BE2CF979D01CD0A2A2CC576453 /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + 9FEC1F12EB515DFCF19288525A7FBAE6 /* FPruneForest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPruneForest.h; path = Firebase/Database/Persistence/FPruneForest.h; sourceTree = ""; }; + A024BF1A97EF24A2E139DAE4E26A7246 /* FUIAccountSettingsOperationUnlinkAccount.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationUnlinkAccount.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUnlinkAccount.m; sourceTree = ""; }; + A068D9D7C318C3DEDB62F09C48DF6E09 /* da.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = da.lproj; path = Auth/FirebaseAuthUI/Strings/da.lproj; sourceTree = ""; }; + A069F158CEFBA4E38C45563122AFCC5F /* FBLPromise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromise.m; path = Sources/FBLPromises/FBLPromise.m; sourceTree = ""; }; + A081B6423331628EACC4D7A73AE127F1 /* random.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = random.h; path = util/random.h; sourceTree = ""; }; + A0ACEEDB9C66A05F00FB2DC2683FD087 /* FIRAuthProtoStartMFAPhoneRequestInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProtoStartMFAPhoneRequestInfo.m; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneRequestInfo.m; sourceTree = ""; }; + A1045ABFBD7DF90A5E84372D88E5C833 /* hu.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = hu.lproj; path = Auth/FirebaseAuthUI/Strings/hu.lproj; sourceTree = ""; }; + A1199F3B6D178FFC9022E990B57BF88D /* FIRMultiFactorSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMultiFactorSession.h; path = FirebaseAuth/Sources/Public/FIRMultiFactorSession.h; sourceTree = ""; }; + A122549B6D85715608C5CBF371E00515 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + A2417F4287F02A9B7CB860818E067D32 /* FIROptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptions.h; path = FirebaseCore/Sources/Public/FIROptions.h; sourceTree = ""; }; + A24AAC884CBBE3470180211F88008142 /* GoogleDataTransport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransport-umbrella.h"; sourceTree = ""; }; + A251FCAE5F4EAAEB842779316E4F5C02 /* FIRInstallationsErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrors.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h; sourceTree = ""; }; + A270BC478BF1E34A0FFDEE765533F5D3 /* coding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = coding.h; path = util/coding.h; sourceTree = ""; }; + A29139C652B1A548F84E6EFC698953C4 /* FIRStorageUpdateMetadataTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUpdateMetadataTask.m; path = FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m; sourceTree = ""; }; + A29EA43E4DC3B153192A8339CC174C3E /* FIRFinalizeMFASignInRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFinalizeMFASignInRequest.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRFinalizeMFASignInRequest.m; sourceTree = ""; }; + A2A5A1EE7BFC5AF902EB876693194B98 /* FIRDatabaseQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseQuery.m; path = Firebase/Database/Api/FIRDatabaseQuery.m; sourceTree = ""; }; + A2A714EBE8E059F6E1C1162A7AD08015 /* FIRDatabase_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase_Private.h; path = Firebase/Database/Api/Private/FIRDatabase_Private.h; sourceTree = ""; }; + A2FB23E8BFBE90DE7FC2150F1FB132A1 /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + A2FB2B9B3D118E4042071207EAD6153F /* zh.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = zh.lproj; path = Auth/FirebaseAuthUI/Strings/zh.lproj; sourceTree = ""; }; + A3BA8163828042C7132F40FBC25E24D5 /* FirebaseAuthUI.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = FirebaseAuthUI.bundle; path = "FirebaseUI-FirebaseAuthUI.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + A3D121E26C7391B5D7DB696193E9698F /* FEventGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventGenerator.m; path = Firebase/Database/FEventGenerator.m; sourceTree = ""; }; + A3E2C01DD82DC9DFC1C6679BEB9F35E1 /* GDTCORAssert.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORAssert.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m; sourceTree = ""; }; + A43B99F4F9A7AFE85D8AC61C327BA44C /* GoogleSignIn.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleSignIn.release.xcconfig; sourceTree = ""; }; + A4C16C9132307023FAF3F4A82725766A /* FirebaseCoreInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCoreInternal.h; path = FirebaseCore/Sources/Private/FirebaseCoreInternal.h; sourceTree = ""; }; + A526C31FD98918B4CE3A59BB0BD27C90 /* FTrackedQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQuery.h; path = Firebase/Database/Persistence/FTrackedQuery.h; sourceTree = ""; }; + A536C5536C394A6E8669C73E0EB32186 /* FUIAccountSettingsOperationDeleteAccount.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAccountSettingsOperationDeleteAccount.m; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationDeleteAccount.m; sourceTree = ""; }; + A54237B6213E123B38287547B3062207 /* c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = c.h; path = include/leveldb/c.h; sourceTree = ""; }; + A54588AA46CA9135DA6EA1DF67064247 /* port_stdcxx.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_stdcxx.h; path = port/port_stdcxx.h; sourceTree = ""; }; + A55165D05F5298D7EC70AC6D256E7480 /* FIRMultiFactorSession+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRMultiFactorSession+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/FIRMultiFactorSession+Internal.h"; sourceTree = ""; }; + A554AF875831B385C25328CECE189540 /* FIRIdentityToolkitRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRIdentityToolkitRequest.h; path = FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.h; sourceTree = ""; }; + A56F42E97685ECB4B0F45C2EAE622DBB /* FImmutableSortedSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedSet.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h; sourceTree = ""; }; + A58F87C6180D374437CE7E706591B563 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + A59B1CF1D3E7FC2F9080D57916333E55 /* pb_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_decode.c; sourceTree = ""; }; + A63980E1EAF8FC62A63C8A59A8AB6541 /* OIDScopes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDScopes.m; path = Source/AppAuthCore/OIDScopes.m; sourceTree = ""; }; + A672DD638BC3C2D318FB66F0D7E6C1F9 /* es-CR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-CR.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-CR.lproj"; sourceTree = ""; }; + A67AFCD9FDFD86A36567F4CA75A18EDD /* FBLPromise+Recover.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Recover.m"; path = "Sources/FBLPromises/FBLPromise+Recover.m"; sourceTree = ""; }; + A6A2A48DDBA7CD20E2D170FF98D7D6E2 /* en-SG.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-SG.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-SG.lproj"; sourceTree = ""; }; + A6A6CEC85A5CC5B5C02A3A53996C6DCB /* FIRUserMetadata_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUserMetadata_Internal.h; path = FirebaseAuth/Sources/User/FIRUserMetadata_Internal.h; sourceTree = ""; }; + A6ACC2CFD2255923C22F0FAE78CA8F2D /* FIRStartMFASignInRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStartMFASignInRequest.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn/FIRStartMFASignInRequest.m; sourceTree = ""; }; + A6D4918D8DF4FD0507640613DA81CC4B /* log_reader.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_reader.cc; path = db/log_reader.cc; sourceTree = ""; }; + A71C4B5D790AC1036C87931CE820B177 /* FIRAuthSettings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthSettings.h; path = FirebaseAuth/Sources/Public/FIRAuthSettings.h; sourceTree = ""; }; + A71D66ABEC259E383B47228B948294EC /* FDataEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FDataEvent.h; path = Firebase/Database/Core/View/FDataEvent.h; sourceTree = ""; }; + A768CAA71B66068FB09E6EAE5A8B0525 /* Firebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Firebase.h; path = CoreOnly/Sources/Firebase.h; sourceTree = ""; }; + A77908716A340BFE5D8D34EE22B8A578 /* fil.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fil.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/fil.lproj; sourceTree = ""; }; + A7842D8719CBBA97D03A9F7A3133A20B /* FIRResetPasswordRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRResetPasswordRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.m; sourceTree = ""; }; + A78967BAA83809158FF45AD8D7E55402 /* FIRInstallationsItem+RegisterInstallationAPI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstallationsItem+RegisterInstallationAPI.h"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h"; sourceTree = ""; }; + A791424A89A3CDA5752E45E7C544B668 /* nb.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = nb.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/nb.lproj; sourceTree = ""; }; + A7950EBD3C0C73CAF6F2AECCB1F0F04E /* FUIStaticContentTableViewController.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIStaticContentTableViewController.xib; path = Auth/FirebaseAuthUI/FUIStaticContentTableViewController.xib; sourceTree = ""; }; + A7AFBD062FA62F077ECC87E01A4138FC /* FPriorityIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPriorityIndex.m; path = Firebase/Database/FPriorityIndex.m; sourceTree = ""; }; + A7B327A0258B05487FBCADDDB623B798 /* FIRInstallationsAPIService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAPIService.h; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h; sourceTree = ""; }; + A7B7105386F708B8C130FB1781D4A137 /* FCompoundHash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundHash.h; path = Firebase/Database/Core/FCompoundHash.h; sourceTree = ""; }; + A80721995C6E55BC9F26D235F75157BC /* FUIAuthSignInButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthSignInButton.m; path = Auth/FirebaseAuthUI/FUIAuthSignInButton.m; sourceTree = ""; }; + A81FD5C759061AA4B7F4E981E801C9BB /* FIRMutableData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData.h; path = Firebase/Database/Public/FIRMutableData.h; sourceTree = ""; }; + A86AE5BDDF81D3355108EB4D4CE575DA /* FirebaseDatabase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseDatabase-Info.plist"; sourceTree = ""; }; + A896F717F028A846414875FFEE157568 /* APLevelDB.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = APLevelDB.mm; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm"; sourceTree = ""; }; + A902EC22E4E7592D1507079756376044 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + A97A1D0B0968B8B21FB213A4A8E8AD35 /* FIRCoreDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsData.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h; sourceTree = ""; }; + A99030435F8DB28FCCE7B7B4819BB6C5 /* GoogleSignIn.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleSignIn.debug.xcconfig; sourceTree = ""; }; + A99400EE0057F9ADD1A81323F1926953 /* FIRGoogleAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGoogleAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRGoogleAuthProvider.h; sourceTree = ""; }; + A99C7A8E7DC4E7B780CCBF06E6C3EF8A /* FChildrenNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildrenNode.m; path = Firebase/Database/Snapshot/FChildrenNode.m; sourceTree = ""; }; + A9C4A684387AAD595A79267AB8478CC2 /* FIRAuthCredential_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthCredential_Internal.h; path = FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h; sourceTree = ""; }; + A9F703C962F2095B7778365C9317974D /* FIRWithdrawMFARequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRWithdrawMFARequest.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.h; sourceTree = ""; }; + A9FA51204A20C57FD2FB2EFDBFFE3B61 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + AA16A2EC6DEB773205D80D76F235DE58 /* FCachePolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCachePolicy.m; path = Firebase/Database/Persistence/FCachePolicy.m; sourceTree = ""; }; + AA19D221880B1D318DD890057CEBF1F3 /* AppAuth-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AppAuth-dummy.m"; sourceTree = ""; }; + AA58215224CE0D047281492EBBA3216C /* FIRInstallationsIIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDTokenStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h; sourceTree = ""; }; + AA6836C316894F3DD346893242595932 /* FWebSocketConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWebSocketConnection.h; path = Firebase/Database/Realtime/FWebSocketConnection.h; sourceTree = ""; }; + AA9B4B8BCB07AC966A24D358AE74A0E6 /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + AAA93E7250E2606BC3CE32C1BCD11A51 /* log_reader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_reader.h; path = db/log_reader.h; sourceTree = ""; }; + AAD4D44993BA05A2CEEDCFB4AEF3E45F /* FIRTransactionResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult.h; path = Firebase/Database/Public/FIRTransactionResult.h; sourceTree = ""; }; + AAF1F950FB05508CDC5E0BADE1A27F22 /* FirebaseAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseAuth.h; path = FirebaseAuth/Sources/Public/FirebaseAuth.h; sourceTree = ""; }; + AAF8E5F6347530C455055D47E32788FE /* FQueryParams.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQueryParams.h; path = Firebase/Database/Core/FQueryParams.h; sourceTree = ""; }; + AB5A9CB8FC820368415F100A55EF934B /* FValidation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValidation.h; path = Firebase/Database/Utilities/FValidation.h; sourceTree = ""; }; + AB8D15C266FE082A037570E11AE0AE14 /* FIRDatabaseReference.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference.h; path = Firebase/Database/Public/FIRDatabaseReference.h; sourceTree = ""; }; + AC0430E28848AB18A3CA8325151A98FD /* ic_visibility_off@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_visibility_off@2x.png"; path = "Auth/FirebaseAuthUI/Resources/ic_visibility_off@2x.png"; sourceTree = ""; }; + AC4C5100114EE4AD832B2C059B9B0B9B /* FUIAuth_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuth_Internal.h; path = Auth/FirebaseAuthUI/FUIAuth_Internal.h; sourceTree = ""; }; + AC61C5ABD2CCCABB38B49666D763500D /* FIRWithdrawMFARequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRWithdrawMFARequest.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll/FIRWithdrawMFARequest.m; sourceTree = ""; }; + AC71EF56D169FAEC6FA1922E3EDE88B0 /* FIRSignUpNewUserRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSignUpNewUserRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.m; sourceTree = ""; }; + ACA0CE3201D296FEA1844CED6E9D0E8D /* histogram.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = histogram.cc; path = util/histogram.cc; sourceTree = ""; }; + ACB1AD1F6F42BF9BB16AE8500CEB3DA7 /* FIRVerifyCustomTokenRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyCustomTokenRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h; sourceTree = ""; }; + ACB7AE213B5C354BC61016F4F3AA5E23 /* FIRAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/FIRAuthProvider.m; sourceTree = ""; }; + AD0A6CCE189FE94F37994AAD4CB73A1B /* FKeepSyncedEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeepSyncedEventRegistration.m; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.m; sourceTree = ""; }; + ADCE0BC750EA080093025FC468D756B3 /* GDTCCTUploader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTUploader.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m; sourceTree = ""; }; + AE31FD42BB2863C4D9CAC980F8085F1A /* FirebaseCore.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.release.xcconfig; sourceTree = ""; }; + AE454B37B7F5959A0D2816E4BAB48C6C /* FIRInstallationsStoredAuthToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredAuthToken.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m; sourceTree = ""; }; + AE90B3E6EEC9E3BF861BA8A809F7298D /* FRepo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo.h; path = Firebase/Database/Core/FRepo.h; sourceTree = ""; }; + AEC5BAE613C9C504615D4DFD6BA5F32E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + AECF8D6DA7C8A464989CB066D473F472 /* FIRAuthErrorUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthErrorUtils.m; path = FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m; sourceTree = ""; }; + AF07CF05D98104373FD3D96B8260E436 /* en-CA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-CA.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-CA.lproj"; sourceTree = ""; }; + AF143C3AEAFA1634232E7FDB22A4A7F2 /* FWriteTreeRef.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTreeRef.m; path = Firebase/Database/Core/FWriteTreeRef.m; sourceTree = ""; }; + AF28C7AA75034B0E472FCB46591FE86D /* OIDRegistrationResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDRegistrationResponse.m; path = Source/AppAuthCore/OIDRegistrationResponse.m; sourceTree = ""; }; + AF35B0BD464B5D45C6B66A9A600F74F5 /* FIRAuthAppCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthAppCredential.m; path = FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.m; sourceTree = ""; }; + AF4370CCD5C550D5805C9E19ADDBB5B3 /* FImmutableSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h; sourceTree = ""; }; + AF4DFD6F05C1DBDF4AB4A397879384A0 /* FIROAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthProvider.m; sourceTree = ""; }; + AF4EA4512BEB4222E9BFDDF30A07AC8D /* FTupleCallbackStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleCallbackStatus.h; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h; sourceTree = ""; }; + AF66366B4FE39EE44F0D31C2EB1B1232 /* GTMSessionFetcher-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GTMSessionFetcher-Info.plist"; sourceTree = ""; }; + AF8A2024FCA85F80B0E6A5BE255D7504 /* FWriteTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTree.m; path = Firebase/Database/Core/FWriteTree.m; sourceTree = ""; }; + AF966A01B41EB868CD964B1A909147EB /* FRepo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepo.m; path = Firebase/Database/Core/FRepo.m; sourceTree = ""; }; + AFCF7CBD5A6947B40B936E1629C4CD6B /* FImmutableSortedSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedSet.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m; sourceTree = ""; }; + AFD9F1C347A7E1767AB75D4D6310C2FC /* GoogleUtilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleUtilities.modulemap; sourceTree = ""; }; + AFD9FA2AEB376B05A4B4A9FFA4D1C6A5 /* FIRUser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRUser.m; path = FirebaseAuth/Sources/User/FIRUser.m; sourceTree = ""; }; + B005A07BEF4B4650B74F86B0F91D2E75 /* FIREmailLinkSignInRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIREmailLinkSignInRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInRequest.h; sourceTree = ""; }; + B014CCA1962E1AD28F0B09CE411EB360 /* Pods-MyExperiences-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-MyExperiences-acknowledgements.markdown"; sourceTree = ""; }; + B01F7EDFE796ECCD43987D342ACF9799 /* FirebaseInstallations-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstallations-umbrella.h"; sourceTree = ""; }; + B0382A72B82D98EB0659D080E198382F /* FPriorityIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPriorityIndex.h; path = Firebase/Database/FPriorityIndex.h; sourceTree = ""; }; + B07EFDEC4F73E46667B5472E98CA5B7E /* sr-Latn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "sr-Latn.lproj"; path = "Auth/FirebaseAuthUI/Strings/sr-Latn.lproj"; sourceTree = ""; }; + B0C412BBE0A796A1761E0B94E8A1A4C2 /* FIRIdentityToolkitRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRIdentityToolkitRequest.m; path = FirebaseAuth/Sources/Backend/FIRIdentityToolkitRequest.m; sourceTree = ""; }; + B0C9BF1BD3D64D58780FCF7D993843EA /* FAtomicNumber.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAtomicNumber.h; path = Firebase/Database/Utilities/FAtomicNumber.h; sourceTree = ""; }; + B0CC498F1F77BEE204AA9B103D245937 /* en-IE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-IE.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-IE.lproj"; sourceTree = ""; }; + B0FA2F0A3D5C566608F18B383B6CF044 /* FIRAuthStoredUserManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthStoredUserManager.h; path = FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.h; sourceTree = ""; }; + B10154179A246D8D0A16DC1C08225929 /* en-IE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-IE.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/en-IE.lproj"; sourceTree = ""; }; + B11DCFFDC5B68C637EBB08CCE356ADFF /* FUIAccountSettingsOperationSignOut.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationSignOut.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationSignOut.h; sourceTree = ""; }; + B213F5865A99165D7CD215C45D137240 /* FIRStoragePath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStoragePath.h; path = FirebaseStorage/Sources/FIRStoragePath.h; sourceTree = ""; }; + B224DAD75F17390167B044A8AC13A27A /* FirebaseUI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseUI-dummy.m"; sourceTree = ""; }; + B2C1368FD864972A677AA6F00D203E6D /* FWriteRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteRecord.m; path = Firebase/Database/Core/FWriteRecord.m; sourceTree = ""; }; + B2C32D7546A54979C5057A1181763D1C /* FirebaseAnalytics.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.release.xcconfig; sourceTree = ""; }; + B2C91601666B923A0EC1E3E55055B56F /* en-CA.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-CA.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-CA.lproj"; sourceTree = ""; }; + B2D180E7D85A1EFB4F921E0D6C62060B /* FIRDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase.h; path = Firebase/Database/Public/FIRDatabase.h; sourceTree = ""; }; + B3178115AB08280B641E901DDB1BD191 /* GoogleDataTransport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransport.modulemap; sourceTree = ""; }; + B31CEFCCA8222DE30CE0A3C9C1694A1B /* it.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = it.lproj; path = Auth/FirebaseAuthUI/Strings/it.lproj; sourceTree = ""; }; + B37F5E42FA68448CE182756873C9A2CC /* FRangedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangedFilter.h; path = Firebase/Database/FRangedFilter.h; sourceTree = ""; }; + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleUtilities.framework; path = GoogleUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B49FFCD7B5EBFCE7B830557C601A9F0A /* FirebaseAuth-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseAuth-umbrella.h"; sourceTree = ""; }; + B52ECB24B1A93B2993DBF10DE2DA98B5 /* filter_block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_block.cc; path = table/filter_block.cc; sourceTree = ""; }; + B530A33CA1805EF305BEC939BCCF6E7D /* es-PY.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PY.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-PY.lproj"; sourceTree = ""; }; + B53E593E59C566978EEABD9BBAE4E82C /* FIRPhoneMultiFactorAssertion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneMultiFactorAssertion.h; path = FirebaseAuth/Sources/Public/FIRPhoneMultiFactorAssertion.h; sourceTree = ""; }; + B54C585EF7038D6E900107B27C41362B /* FIRStorageTaskSnapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTaskSnapshot.m; path = FirebaseStorage/Sources/FIRStorageTaskSnapshot.m; sourceTree = ""; }; + B59BE61A40373B7371A718989F31D704 /* FIRPhoneMultiFactorInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRPhoneMultiFactorInfo.m; path = FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo.m; sourceTree = ""; }; + B5B759E77F07B7A43FB5DFDE3AEBCD33 /* FListenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenProvider.m; path = Firebase/Database/Core/FListenProvider.m; sourceTree = ""; }; + B5D26B5B77EF3AE1B591E57CD37A8A72 /* db_impl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_impl.h; path = db/db_impl.h; sourceTree = ""; }; + B5F0E87509D9331164A5F4D765B1A3D0 /* OIDExternalUserAgentRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentRequest.h; path = Source/AppAuthCore/OIDExternalUserAgentRequest.h; sourceTree = ""; }; + B6A87CF7908130E325DFCD7785AF2613 /* FirebaseStorage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseStorage.modulemap; sourceTree = ""; }; + B6BD3FBBC2A8E810BCD6B7AD16D08BCC /* FEventGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventGenerator.h; path = Firebase/Database/FEventGenerator.h; sourceTree = ""; }; + B70A99DE047CDFD48AEAF4818A9AA25B /* version_set.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_set.h; path = db/version_set.h; sourceTree = ""; }; + B7698798113828A6F12BD9B8EC907A4B /* FIRGetOOBConfirmationCodeRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetOOBConfirmationCodeRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h; sourceTree = ""; }; + B780FFAC1852977D9C50DEB819B56185 /* OIDExternalUserAgentCatalyst.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentCatalyst.h; path = Source/AppAuth/iOS/OIDExternalUserAgentCatalyst.h; sourceTree = ""; }; + B790DE03DD206859035C01A0ECA835C7 /* FIRGameCenterAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGameCenterAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.m; sourceTree = ""; }; + B7EBBBA5B262CA6C018FC09D4BDA7CBD /* nanopb-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-umbrella.h"; sourceTree = ""; }; + B7FE9445781AA6E6E3D1ECB979847E15 /* GULHeartbeatDateStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULHeartbeatDateStorage.h; path = GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h; sourceTree = ""; }; + B85875DD11E278FBC02338C96C934B34 /* FUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUtilities.h; path = Firebase/Database/Utilities/FUtilities.h; sourceTree = ""; }; + B89C71BCD83F5C915E0B7B88E0783F5A /* OIDClientMetadataParameters.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDClientMetadataParameters.h; path = Source/AppAuthCore/OIDClientMetadataParameters.h; sourceTree = ""; }; + B8FC9290AD16001E5097C8CDEDCEB32E /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + B97D7D6E5E4BC068C64A9517329F59DC /* FTupleStringNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleStringNode.h; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.h; sourceTree = ""; }; + B9C76868E9938C4102BD1215FD5A8374 /* firebasecore.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = firebasecore.nanopb.h; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h; sourceTree = ""; }; + B9DB9D346A7C30019219602974216E5C /* en.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = en.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/en.lproj; sourceTree = ""; }; + BA00DAB93EF0A75C56ED6785FACD5EF3 /* FIRAuthProto.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProto.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProto.h; sourceTree = ""; }; + BAAEF18BC7684AEDE7B7A4B4E04FB187 /* FIRFacebookAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRFacebookAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/Facebook/FIRFacebookAuthProvider.m; sourceTree = ""; }; + BB397D64A004B2E58E996CA6126F9E5D /* FIRSetAccountInfoResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSetAccountInfoResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.m; sourceTree = ""; }; + BB4C2140E68F6C9C0DA2ED701FC0DADB /* Firebase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.release.xcconfig; sourceTree = ""; }; + BB721B72DF6ED457D6DA175690F307F3 /* cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = cache.cc; path = util/cache.cc; sourceTree = ""; }; + BBC868C8D7509594738EB3FF2E0097AF /* es-US.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-US.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-US.lproj"; sourceTree = ""; }; + BBE953CA3053CC11FBB998F65D10C853 /* es-UY.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-UY.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-UY.lproj"; sourceTree = ""; }; + BC2B894E2BDEB2C236F169221286AD5B /* ja.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ja.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ja.lproj; sourceTree = ""; }; + BC664C1A73AF5E0E4D8D49709109472E /* format.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = format.cc; path = table/format.cc; sourceTree = ""; }; + BCA966424292F2B2B3A4A968426A30E7 /* FNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNode.h; path = Firebase/Database/Snapshot/FNode.h; sourceTree = ""; }; + BCB47C109880284CCAC55AF2BD005BFB /* FBLPromise+Always.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Always.m"; path = "Sources/FBLPromises/FBLPromise+Always.m"; sourceTree = ""; }; + BD266F211E48CEE436ECB2082049DFAF /* GDTCORTransformer_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h; sourceTree = ""; }; + BD30BDBFF431CB4399110E9416A8E470 /* FIRAppAssociationRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAppAssociationRegistration.m; path = FirebaseCore/Sources/FIRAppAssociationRegistration.m; sourceTree = ""; }; + BD85954CCC85183D912107A4874B556F /* FUIAuthUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthUtils.h; path = Auth/FirebaseAuthUI/FUIAuthUtils.h; sourceTree = ""; }; + BDB88ED4C4E94AA853AEA687BD141AC8 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + BDE67C480BC4E7C0C8D3379267B21193 /* OIDAuthorizationService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDAuthorizationService.m; path = Source/AppAuthCore/OIDAuthorizationService.m; sourceTree = ""; }; + BDEC68EAE51158E1F4BB5115466D6247 /* GULSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSwizzler.m; path = GoogleUtilities/MethodSwizzler/GULSwizzler.m; sourceTree = ""; }; + BDF69634B5F3A7C722770C9FA296E0B7 /* bn.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = bn.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/bn.lproj; sourceTree = ""; }; + BDF753A2E9438074A71EB24C6EE3B5A7 /* GTMSessionFetcher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMSessionFetcher-umbrella.h"; sourceTree = ""; }; + BE2D05806F5FFBEDF2E3296B2922BC7B /* vi.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = vi.lproj; path = Auth/FirebaseAuthUI/Strings/vi.lproj; sourceTree = ""; }; + BE4803EBD15BE98DB688A0189ECD4ED8 /* FIRInstallationsLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsLogger.h; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.h; sourceTree = ""; }; + BE57096B74561E4E5589CC94B228D138 /* uk.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = uk.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/uk.lproj; sourceTree = ""; }; + BE6ED932E7AAD7F346281275A45DC1B7 /* FChildChangeAccumulator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildChangeAccumulator.m; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m; sourceTree = ""; }; + BE847A5DCB4BFC93207699CCE355AD02 /* FIRSignInWithGameCenterResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSignInWithGameCenterResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h; sourceTree = ""; }; + BEB00CA7F1B74B70E55D98ACA2FEE9E8 /* FIRTwitterAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTwitterAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRTwitterAuthProvider.h; sourceTree = ""; }; + BEE24FC0665340E787AA4D29456F0DE1 /* id.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = id.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/id.lproj; sourceTree = ""; }; + BF1EF2B382CEE39048BFA8A04FA59482 /* FIRAuthUIDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthUIDelegate.h; path = FirebaseAuth/Sources/Public/FIRAuthUIDelegate.h; sourceTree = ""; }; + BF2AEE9791F5228164E2A159B584198C /* FIRStorageComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageComponent.h; path = FirebaseStorage/Sources/FIRStorageComponent.h; sourceTree = ""; }; + BF78F6F7E220218B75FDE0FF75690CAA /* logging.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = logging.cc; path = util/logging.cc; sourceTree = ""; }; + BF8A0755D032262E220C5286C9CCF2CF /* db_iter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_iter.h; path = db/db_iter.h; sourceTree = ""; }; + C01BC2C5447DFEE202AD31B17BA8FEA8 /* FValueEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueEventRegistration.m; path = Firebase/Database/Core/View/FValueEventRegistration.m; sourceTree = ""; }; + C0B11264065182D6FAD716FE09C948EE /* fbase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fbase64.h; path = Firebase/Database/third_party/SocketRocket/fbase64.h; sourceTree = ""; }; + C18E3D1267F99711A68A8B02BF9FFDD7 /* FIRInstallationsErrorUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrorUtil.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h; sourceTree = ""; }; + C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GTMSessionFetcher.framework; path = GTMSessionFetcher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C1AF546369B668B9AAEA63DF300E02FD /* GTMAppAuth-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMAppAuth-prefix.pch"; sourceTree = ""; }; + C1F6B850C4D596D278B785A539B55B1E /* GDTCORDataFuture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORDataFuture.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m; sourceTree = ""; }; + C2108C3AC4A847D23C1CED0BA5C0EC93 /* FEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEmptyNode.m; path = Firebase/Database/Snapshot/FEmptyNode.m; sourceTree = ""; }; + C21C89AC19083B376E164BCC661CB8D9 /* FIRUserMetadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRUserMetadata.m; path = FirebaseAuth/Sources/User/FIRUserMetadata.m; sourceTree = ""; }; + C22B8910D6EF1F33FCF463C140B9FAF9 /* FIRAuthAPNSTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthAPNSTokenManager.m; path = FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.m; sourceTree = ""; }; + C24569803038905A315E8886A49F56C5 /* crc32c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = crc32c.cc; path = util/crc32c.cc; sourceTree = ""; }; + C25D07BAAE13143BC5F5C71355C0D5B6 /* FIRUserMetadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUserMetadata.h; path = FirebaseAuth/Sources/Public/FIRUserMetadata.h; sourceTree = ""; }; + C2A84F61584DBCC3BD946DCDB89CB968 /* FIRSendVerificationCodeRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSendVerificationCodeRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeRequest.m; sourceTree = ""; }; + C2C0C1E05732AAA942EE2412CFBE94DB /* FirebaseStorage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseStorage.release.xcconfig; sourceTree = ""; }; + C35495E3A2AE522CF824CEDE83F84FA4 /* FirebaseCore-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCore-Info.plist"; sourceTree = ""; }; + C35B22038D2BC9F2DD0326DB7D408CD9 /* FAckUserWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAckUserWrite.m; path = Firebase/Database/Core/Operation/FAckUserWrite.m; sourceTree = ""; }; + C3671B246F2292948552AA5DC9D688A0 /* ms.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ms.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ms.lproj; sourceTree = ""; }; + C38527266A6D5DDFB333ABB2566D6783 /* bloom.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = bloom.cc; path = util/bloom.cc; sourceTree = ""; }; + C38D7625DDE875B5097AAC4D90B1F41D /* FirebaseDatabase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseDatabase-dummy.m"; sourceTree = ""; }; + C391CAD9145F4C9DB23A38E59BB34A20 /* FArraySortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FArraySortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m; sourceTree = ""; }; + C40D486D4F445531BAB7739A5F3D2AF6 /* FIRStorageDownloadTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDownloadTask_Private.h; path = FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h; sourceTree = ""; }; + C454F063088B3509C6ED0D11F3FF4E73 /* es.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = es.lproj; path = Auth/FirebaseAuthUI/Strings/es.lproj; sourceTree = ""; }; + C457F92BE0D82B39FB3D3302C73322C8 /* sl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sl.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/sl.lproj; sourceTree = ""; }; + C47465A0B2EB8E8D479EAC036DD13898 /* GDTCORDataFuture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORDataFuture.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORDataFuture.h; sourceTree = ""; }; + C48ADF74490C4A45C87650023E850992 /* AppAuth.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AppAuth.debug.xcconfig; sourceTree = ""; }; + C499E907E739C12D9058162F8970BAEF /* FBLPromise+Any.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Any.h"; path = "Sources/FBLPromises/include/FBLPromise+Any.h"; sourceTree = ""; }; + C4A53C14BCDA2F6609BF3286C408518F /* FBLPromise+Async.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Async.h"; path = "Sources/FBLPromises/include/FBLPromise+Async.h"; sourceTree = ""; }; + C4D13117E55C177BC67ADD141D7A6557 /* FIRPhoneAuthCredential_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneAuthCredential_Internal.h; path = FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h; sourceTree = ""; }; + C4E8A02EA89196599EEA4611A384C74A /* FUIAccountSettingsOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperation.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.h; sourceTree = ""; }; + C56E3C6C0454607B87EA00A5D33CAB73 /* FIREmailPasswordAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIREmailPasswordAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/Email/FIREmailPasswordAuthCredential.m; sourceTree = ""; }; + C5B786A2F794E5BFB62AFC684ED5B115 /* FIRAuthAPNSTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthAPNSTokenManager.h; path = FirebaseAuth/Sources/SystemService/FIRAuthAPNSTokenManager.h; sourceTree = ""; }; + C5F00DE74D2EC6196997C150EB6ECE06 /* de.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = de.lproj; path = Auth/FirebaseAuthUI/Strings/de.lproj; sourceTree = ""; }; + C612507BFEF47D61B5266674121F2A68 /* FirebaseGoogleAuthUI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseGoogleAuthUI.h; path = GoogleAuth/FirebaseGoogleAuthUI/FirebaseGoogleAuthUI.h; sourceTree = ""; }; + C64029352A35B37DDA881D4E6ACF6C1E /* FUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUtilities.m; path = Firebase/Database/Utilities/FUtilities.m; sourceTree = ""; }; + C6959E1A1109365FD844CBC9D553F283 /* FIRAuthInternalErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInternalErrors.h; path = FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h; sourceTree = ""; }; + C6A572D31316806D9DE6D2194E98FBE0 /* GoogleDataTransportCCTSupport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransportCCTSupport.debug.xcconfig; sourceTree = ""; }; + C6B3A10FE7BA9E0E113004E04AB0D9FA /* FSyncTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncTree.m; path = Firebase/Database/Core/FSyncTree.m; sourceTree = ""; }; + C6CF3BD228981A8B6F7FA16F10B7BE6B /* FirebaseUI.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseUI.debug.xcconfig; sourceTree = ""; }; + C6E90123E0824FF1FE9CD046989FCD25 /* FViewProcessorResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessorResult.m; path = Firebase/Database/FViewProcessorResult.m; sourceTree = ""; }; + C6F70D4FA6DDFC1F1BE8ADAF97E4F5DF /* GULSecureCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSecureCoding.h; path = GoogleUtilities/Environment/Public/GULSecureCoding.h; sourceTree = ""; }; + C74BB36833DAE2734F5679B8EE2E04FD /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SafariServices.framework; sourceTree = DEVELOPER_DIR; }; + C74F354DE76EFF3D897FDE22F1864112 /* FIRPhoneMultiFactorGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneMultiFactorGenerator.h; path = FirebaseAuth/Sources/Public/FIRPhoneMultiFactorGenerator.h; sourceTree = ""; }; + C75B68AA4C55046DD41596EEF217E773 /* OIDEndSessionResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDEndSessionResponse.m; path = Source/AppAuthCore/OIDEndSessionResponse.m; sourceTree = ""; }; + C7618A96808C4D7CEB9824787ABB4DD4 /* GDTCOREventDataObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventDataObject.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h; sourceTree = ""; }; + C76496A8B14E858B7350925B0A20A7DA /* FIRGetAccountInfoResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetAccountInfoResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.m; sourceTree = ""; }; + C7797DEC71A199778D2E303EE512CA30 /* FUIAuth.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuth.m; path = Auth/FirebaseAuthUI/FUIAuth.m; sourceTree = ""; }; + C78C74720DE09E30B23A6F9C9B6F5242 /* FBLPromise+Do.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Do.m"; path = "Sources/FBLPromises/FBLPromise+Do.m"; sourceTree = ""; }; + C824D703137DD9400773104180604FD7 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + C85496CC24BDC7756948ADF2E7D60E04 /* FIRInstallationsStoredItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredItem.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h; sourceTree = ""; }; + C877AEB4DB96DADD3B3B880F11E807FB /* FImmutableTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableTree.h; path = Firebase/Database/Core/Utilities/FImmutableTree.h; sourceTree = ""; }; + C8811E8ED5B4CA6329322D2ECD3D3AEA /* GoogleSignIn.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleSignIn.framework; path = Frameworks/GoogleSignIn.framework; sourceTree = ""; }; + C8819DA241A028BAD9315C60199BE863 /* FUIAuthErrorUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthErrorUtils.m; path = Auth/FirebaseAuthUI/FUIAuthErrorUtils.m; sourceTree = ""; }; + C8C4908AAA89E23228B4BAE39DC3B770 /* FIRVerifyPhoneNumberResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyPhoneNumberResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPhoneNumberResponse.m; sourceTree = ""; }; + C8DFE6DAEF4281B9CBB00EC08215796B /* FIRUserInfoImpl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRUserInfoImpl.m; path = FirebaseAuth/Sources/User/FIRUserInfoImpl.m; sourceTree = ""; }; + C8FB088C56A528C234F4F1E509AF3A15 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; + C90626A1C745B85C9BAF1B2F0D9A7B81 /* FBLPromise+Race.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Race.h"; path = "Sources/FBLPromises/include/FBLPromise+Race.h"; sourceTree = ""; }; + C932FA22B4630537177123F6782EFBC2 /* GULLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLogger.h; path = GoogleUtilities/Logger/Private/GULLogger.h; sourceTree = ""; }; + C9833FD8B66A1AA07AFF0687BAA33286 /* FIRStorageTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTask.m; path = FirebaseStorage/Sources/FIRStorageTask.m; sourceTree = ""; }; + C9865EBDD0EB8C79D569F548638FCC3D /* sr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = sr.lproj; path = Auth/FirebaseAuthUI/Strings/sr.lproj; sourceTree = ""; }; + C9918A4D64494ADCF2E748DEA552D263 /* FirebaseAuth.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseAuth.modulemap; sourceTree = ""; }; + C9A38DCEB8119B8F88A776D0122E0642 /* FIRUser_Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRUser_Internal.h; path = FirebaseAuth/Sources/User/FIRUser_Internal.h; sourceTree = ""; }; + C9B6A09B272C1AF4BC48955E6BB468C5 /* FIRInstallationsIIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m; sourceTree = ""; }; + C9F72563209A23CBD0D09F13E342C5F8 /* GULKeychainStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULKeychainStorage.h; path = GoogleUtilities/Environment/Public/GULKeychainStorage.h; sourceTree = ""; }; + CA29C0CFDAD423D0106AAC1D67A0170D /* crc32c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = crc32c.h; path = util/crc32c.h; sourceTree = ""; }; + CA3DE504B14BEEF56B3ABB1C443B66D5 /* OIDAuthState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthState.h; path = Source/AppAuthCore/OIDAuthState.h; sourceTree = ""; }; + CAD238E59070BFF625623ECA05A24EBE /* FIRTransactionResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRTransactionResult.m; path = Firebase/Database/Api/FIRTransactionResult.m; sourceTree = ""; }; + CB21872684931D690D8AB43AC75C1930 /* FViewCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewCache.h; path = Firebase/Database/Core/View/FViewCache.h; sourceTree = ""; }; + CB2D63A74DA934A6BEF857D02B49169F /* FIRGoogleAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGoogleAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/Google/FIRGoogleAuthCredential.m; sourceTree = ""; }; + CB61E9165D81B890E80D2A1EA5182F06 /* FIRAuthBackend+MultiFactor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRAuthBackend+MultiFactor.h"; path = "FirebaseAuth/Sources/Backend/FIRAuthBackend+MultiFactor.h"; sourceTree = ""; }; + CB8FE127E94323EA8191DC5075AED4FE /* es-HN.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-HN.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-HN.lproj"; sourceTree = ""; }; + CBA6A06C975D6C6C939DB4CB58EF49F8 /* FIRStorageDownloadTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDownloadTask.h; path = FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h; sourceTree = ""; }; + CBA708B893BBC717AC514C1090F7E389 /* AppAuth-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AppAuth-prefix.pch"; sourceTree = ""; }; + CBB066214D917EE5CF525A00A0789398 /* FTupleObjectNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjectNode.h; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.h; sourceTree = ""; }; + CC289465F3C72999640A1007EB3AB692 /* FIRAuthProtoMFAEnrollment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthProtoMFAEnrollment.m; path = FirebaseAuth/Sources/Backend/RPC/Proto/FIRAuthProtoMFAEnrollment.m; sourceTree = ""; }; + CC316F2270A94C0F8B764AC4D6CE36E7 /* FTuplePathValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTuplePathValue.m; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.m; sourceTree = ""; }; + CC5FC2B13E49CF3005150C72BB9FAA4F /* FUIAccountSettingsOperationUpdatePassword.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationUpdatePassword.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdatePassword.h; sourceTree = ""; }; + CD154F70A82503F71907F09DA04D6A82 /* FIRVerifyPasswordResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVerifyPasswordResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyPasswordResponse.m; sourceTree = ""; }; + CD1796471948B825202E4B28A5B2A6B9 /* FIRPhoneMultiFactorAssertion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRPhoneMultiFactorAssertion.m; path = FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorAssertion.m; sourceTree = ""; }; + CD681182A0A791D44FA0677AAFE46C33 /* ln.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ln.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/ln.lproj; sourceTree = ""; }; + CDB74299006EB164009D493442C606F5 /* FIRAuthInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInterop.h; path = Interop/Auth/Public/FIRAuthInterop.h; sourceTree = ""; }; + CDC596C717FC35E61C792FFD5B68DCDE /* OIDExternalUserAgent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgent.h; path = Source/AppAuthCore/OIDExternalUserAgent.h; sourceTree = ""; }; + CDFA7D192C54AC5633BAC1203D5FB145 /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + CE21C56EF37A104800F9B6C5FFFFA0DD /* FIRResetPasswordResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRResetPasswordResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.h; sourceTree = ""; }; + CE49BDFC8463EC230FD4E8C9B3385281 /* FirebaseGoogleAuthUI.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = FirebaseGoogleAuthUI.bundle; path = "FirebaseUI-FirebaseGoogleAuthUI.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; + CE72AB024AB58E38E7CAAC21CEFD758A /* FIRVerifyClientRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyClientRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientRequest.h; sourceTree = ""; }; + CE95DF51DF0284663E849AF264C11DD3 /* builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = builder.cc; path = db/builder.cc; sourceTree = ""; }; + CE9B81EED1EAD62E147C5B7DE06E7DE9 /* OIDRegistrationResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDRegistrationResponse.h; path = Source/AppAuthCore/OIDRegistrationResponse.h; sourceTree = ""; }; + CEA28D4D4EDF2349738CB345D7EAA2FB /* FIRAuthDataResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthDataResult.h; path = FirebaseAuth/Sources/Public/FIRAuthDataResult.h; sourceTree = ""; }; + CEADACE08A5687E217E73FEB4D216E2D /* OIDRegistrationRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDRegistrationRequest.m; path = Source/AppAuthCore/OIDRegistrationRequest.m; sourceTree = ""; }; + CEBEF2F06D0AD7AA80B541C2D95934CE /* es-AR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-AR.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-AR.lproj"; sourceTree = ""; }; + CEC1393DC856702660ACD7A0599DBD56 /* FIRSignInWithGameCenterRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSignInWithGameCenterRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h; sourceTree = ""; }; + CED22AA9ED7E6EE034D56F18A5F55FC0 /* FBLPromise+Always.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Always.h"; path = "Sources/FBLPromises/include/FBLPromise+Always.h"; sourceTree = ""; }; + CEE9C52C8EB244E7F293F1632DCEC5EF /* GULNetworkURLSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkURLSession.m; path = GoogleUtilities/Network/GULNetworkURLSession.m; sourceTree = ""; }; + CEFFC93E93A7DC5787D5DF680C4AE458 /* filename.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filename.cc; path = db/filename.cc; sourceTree = ""; }; + CFAAD0E22DA01E9DCCA50AD43C753D9F /* FIRCoreDiagnosticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsInterop.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h; sourceTree = ""; }; + CFD98378F7C00DB91E8F99CDD3B231A9 /* GULHeartbeatDateStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULHeartbeatDateStorage.m; path = GoogleUtilities/Environment/GULHeartbeatDateStorage.m; sourceTree = ""; }; + CFDAECD713E8EE3C5428D7BCBF22111C /* FCachePolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCachePolicy.h; path = Firebase/Database/Persistence/FCachePolicy.h; sourceTree = ""; }; + CFECDB2901F99E856524A436F0735545 /* FirebaseUI-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseUI-Info.plist"; sourceTree = ""; }; + CFF7FA3C082DDECFA0AAD760E36D8078 /* GDTCORConsoleLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORConsoleLogger.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h; sourceTree = ""; }; + D00558C0328CCDB118481BC1BB4058F2 /* FCompleteChildSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompleteChildSource.h; path = Firebase/Database/Core/View/Filter/FCompleteChildSource.h; sourceTree = ""; }; + D0347ABD7E493B8A79752245481CB399 /* OIDServiceConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDServiceConfiguration.h; path = Source/AppAuthCore/OIDServiceConfiguration.h; sourceTree = ""; }; + D05CA2DAADBBCFD2217247BCBCD077D4 /* FIRRetryHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRRetryHelper.h; path = Firebase/Database/Core/Utilities/FIRRetryHelper.h; sourceTree = ""; }; + D06BB08F59112DF40E024F3DCB8BA877 /* FTupleNodePath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleNodePath.m; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.m; sourceTree = ""; }; + D11EE5273DF1F4D4E3FDEE12058DFDAC /* FIRAuthDispatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthDispatcher.h; path = FirebaseAuth/Sources/Auth/FIRAuthDispatcher.h; sourceTree = ""; }; + D15C1FD503313790B31F95082523E068 /* FirebaseCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCore.h; path = FirebaseCore/Sources/Public/FirebaseCore.h; sourceTree = ""; }; + D16DC9E195D3C24653FD42E36D93874D /* FMaxNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMaxNode.m; path = Firebase/Database/FMaxNode.m; sourceTree = ""; }; + D18899BE4BC7E2D4F952DB97896F1A68 /* FIRStorageListTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListTask.h; path = FirebaseStorage/Sources/FIRStorageListTask.h; sourceTree = ""; }; + D191AC962BC4DF1A4C9B41B31D176C69 /* FChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChange.h; path = Firebase/Database/Core/View/FChange.h; sourceTree = ""; }; + D1B62426B683A0486229605D8AF442B2 /* GULAppDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h; sourceTree = ""; }; + D203DE15B02674646A391ECDC4236920 /* GoogleUtilities.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.debug.xcconfig; sourceTree = ""; }; + D20FAB51BF2E33A9F29B6692D52010B4 /* FMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMerge.m; path = Firebase/Database/Core/Operation/FMerge.m; sourceTree = ""; }; + D2416E1A611AAAA6CE13CE9FB3A88784 /* FIRAuthNotificationManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthNotificationManager.m; path = FirebaseAuth/Sources/SystemService/FIRAuthNotificationManager.m; sourceTree = ""; }; + D2614520CA43EA86616C7D7EF35F49E9 /* FConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConstants.m; path = Firebase/Database/Constants/FConstants.m; sourceTree = ""; }; + D26F148081403A34009C3E64571BB81E /* FChildEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildEventRegistration.m; path = Firebase/Database/Core/View/FChildEventRegistration.m; sourceTree = ""; }; + D2933987BB6A2053504823F17604CAFE /* block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block.cc; path = table/block.cc; sourceTree = ""; }; + D2A7778C875EA74A7A8967EDFCD4A25B /* FIRAuthTokenResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthTokenResult.m; path = FirebaseAuth/Sources/Auth/FIRAuthTokenResult.m; sourceTree = ""; }; + D2DEB829F75D19F6A96A02CE8E216FA1 /* FIRStorageTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTask_Private.h; path = FirebaseStorage/Sources/FIRStorageTask_Private.h; sourceTree = ""; }; + D2DEEA5B92D2B175ECEDC2E2557D596A /* FPendingPut.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPendingPut.h; path = Firebase/Database/Persistence/FPendingPut.h; sourceTree = ""; }; + D2E9C90D84A48DE2D192DE4878590DC3 /* OIDGrantTypes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDGrantTypes.m; path = Source/AppAuthCore/OIDGrantTypes.m; sourceTree = ""; }; + D320ABBA071441793237FDCC5BF2906A /* FEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRegistration.h; path = Firebase/Database/Core/View/FEventRegistration.h; sourceTree = ""; }; + D32F42267B26545CE5E602067ACDC089 /* ic_google@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_google@3x.png"; path = "GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google@3x.png"; sourceTree = ""; }; + D3C1B3F5110E2256AB2C545D67205C5F /* GULMutableDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULMutableDictionary.m; path = GoogleUtilities/Network/GULMutableDictionary.m; sourceTree = ""; }; + D46BE344296E1A185ACCE52FC07459CE /* FUIPasswordTableViewCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIPasswordTableViewCell.xib; path = Auth/FirebaseAuthUI/AccountManagement/FUIPasswordTableViewCell.xib; sourceTree = ""; }; + D4B1169E73887E37BA13394C51E86E9D /* Pods-MyExperiences-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-MyExperiences-umbrella.h"; sourceTree = ""; }; + D4DC8D9D0355EBB0F68A676013F799AC /* FPathIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPathIndex.h; path = Firebase/Database/FPathIndex.h; sourceTree = ""; }; + D508A6DD4E5CBF53FD46E6F4ACBE445F /* PromisesObjC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PromisesObjC.release.xcconfig; sourceTree = ""; }; + D532471374ECD1325BAAA8585722C50E /* en-AU.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "en-AU.lproj"; path = "Auth/FirebaseAuthUI/Strings/en-AU.lproj"; sourceTree = ""; }; + D55CA217A8FE4CCD968B2FB20090140E /* FQuerySpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQuerySpec.h; path = Firebase/Database/Core/FQuerySpec.h; sourceTree = ""; }; + D569EBF0B43DFF73C4402B67F722476A /* FOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperation.h; path = Firebase/Database/Core/Operation/FOperation.h; sourceTree = ""; }; + D591A8AD1DC179AB95D8C88D42E28597 /* ic_visibility@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_visibility@3x.png"; path = "Auth/FirebaseAuthUI/Resources/ic_visibility@3x.png"; sourceTree = ""; }; + D5BC3E7F58942D74E36BDFA2CE60CE9A /* GDTCORUploadCoordinator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadCoordinator.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h; sourceTree = ""; }; + D5C4CD5C56186305607180E61C480F0C /* FLLRBValueNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBValueNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h; sourceTree = ""; }; + D5FBD9CA1599240429F1765EBF7ED323 /* GDTCCTPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTPrioritizer.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h; sourceTree = ""; }; + D6139A789A449EA83DA37F5C9FF5DD77 /* FIRRetryHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRRetryHelper.m; path = Firebase/Database/Core/Utilities/FIRRetryHelper.m; sourceTree = ""; }; + D613FF318A802CAA63501906CD9204BC /* FIRFinalizeMFAEnrollmentRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFinalizeMFAEnrollmentRequest.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentRequest.h; sourceTree = ""; }; + D678FD741DD09088553BA3DC1E003846 /* GoogleUtilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-umbrella.h"; sourceTree = ""; }; + D6AB56177AAFE39BC48DAAC32ACCF3E3 /* es-419.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-419.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-419.lproj"; sourceTree = ""; }; + D6E3C4C5F3AD43FEBF6E81A4964001A8 /* GTMSessionFetcherLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcherLogging.h; path = Source/GTMSessionFetcherLogging.h; sourceTree = ""; }; + D7918CAF17ADB04CA0D829A49A5E2583 /* table_cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_cache.cc; path = db/table_cache.cc; sourceTree = ""; }; + D79C916C4A7F1CD706F33D10361AD2A1 /* FIRStorageReference.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageReference.h; path = FirebaseStorage/Sources/Public/FIRStorageReference.h; sourceTree = ""; }; + D7BB87477E1647138F76960431BA7280 /* de-AT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "de-AT.lproj"; path = "Auth/FirebaseAuthUI/Strings/de-AT.lproj"; sourceTree = ""; }; + D7FBF775D2A98B0943509C6C0492F77D /* FIRDependency.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDependency.m; path = FirebaseCore/Sources/FIRDependency.m; sourceTree = ""; }; + D8115227BAC33FB3D00E2975EE0BD24C /* FIRPhoneMultiFactorInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRPhoneMultiFactorInfo.h; path = FirebaseAuth/Sources/Public/FIRPhoneMultiFactorInfo.h; sourceTree = ""; }; + D821A20F4F239BB23077D1E020CD4F02 /* OIDExternalUserAgentIOSCustomBrowser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentIOSCustomBrowser.h; path = Source/AppAuth/iOS/OIDExternalUserAgentIOSCustomBrowser.h; sourceTree = ""; }; + D85A7B28B871DD677E7668E92BB6D96A /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + D8E51FA8CD9E9B5E68B3EC07F9539215 /* GoogleDataTransportCCTSupport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransportCCTSupport.release.xcconfig; sourceTree = ""; }; + D94FE53E1C3A87669A08349FFCB1A1F9 /* snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = snapshot.h; path = db/snapshot.h; sourceTree = ""; }; + D977A66079935F32A4225D1C90E2615B /* FServerValues.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FServerValues.m; path = Firebase/Database/Core/FServerValues.m; sourceTree = ""; }; + D983B95F647C6BB9155FCAEA8E9C39AF /* GULMutableDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULMutableDictionary.h; path = GoogleUtilities/Network/Private/GULMutableDictionary.h; sourceTree = ""; }; + D9C51A32FED68D67E048C2F602C45FE5 /* table_cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_cache.h; path = db/table_cache.h; sourceTree = ""; }; + D9E223315FB9AADC49B259DD2B5AF5BF /* FIRAuthURLPresenter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthURLPresenter.h; path = FirebaseAuth/Sources/Utilities/FIRAuthURLPresenter.h; sourceTree = ""; }; + D9E2521795EDDB2463612C8580708673 /* FIRDeleteAccountRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDeleteAccountRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountRequest.h; sourceTree = ""; }; + DABCC02033CB02917A53BDE950562EF9 /* FPersistenceManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistenceManager.h; path = Firebase/Database/Persistence/FPersistenceManager.h; sourceTree = ""; }; + DAEE1F42C1FC3226D38F0A8043D355D4 /* FValueIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueIndex.h; path = Firebase/Database/FValueIndex.h; sourceTree = ""; }; + DAF42C313DED2C3D2F5F3C5156B732A6 /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + DAF9DED7488ECE428D645CC657AD96A7 /* FIRGitHubAuthProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGitHubAuthProvider.m; path = FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthProvider.m; sourceTree = ""; }; + DB0CC50DFD83B710854E5FB52D9DA568 /* FUIAccountSettingsViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsViewController.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsViewController.h; sourceTree = ""; }; + DB555A10BABB5FF3340F0DA9AA9E7525 /* GULNetwork.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetwork.h; path = GoogleUtilities/Network/Private/GULNetwork.h; sourceTree = ""; }; + DB6D2539EA7C1522AC8F8066C70BDAF5 /* FIRMultiFactorInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMultiFactorInfo.h; path = FirebaseAuth/Sources/Public/FIRMultiFactorInfo.h; sourceTree = ""; }; + DB941D9DDE37F386275A2A26D65A2292 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + DBE2AF1FF99BA0861976B62FD7FD819E /* FIRDatabaseQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery.h; path = Firebase/Database/Public/FIRDatabaseQuery.h; sourceTree = ""; }; + DC32670B925412C8F39FD6CAB0A08327 /* FIRCoreDiagnosticsConnector.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnosticsConnector.m; path = FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m; sourceTree = ""; }; + DC72213D4B3FE7DE0AE14E86B63763C3 /* FIRCreateAuthURIResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCreateAuthURIResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h; sourceTree = ""; }; + DCE3112310721644BD336BAD8E71CECE /* pt-BR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "pt-BR.lproj"; path = "Auth/FirebaseAuthUI/Strings/pt-BR.lproj"; sourceTree = ""; }; + DCF3B50D1BFBD7F6BA12307093BA9BD2 /* es-UY.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-UY.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/es-UY.lproj"; sourceTree = ""; }; + DD0492AB09814CBF428CF9310A7DF7BD /* OIDURLSessionProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDURLSessionProvider.m; path = Source/AppAuthCore/OIDURLSessionProvider.m; sourceTree = ""; }; + DD0D0E3CC089D8D56B6F1EA76C078E22 /* FIRSecureTokenService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSecureTokenService.h; path = FirebaseAuth/Sources/SystemService/FIRSecureTokenService.h; sourceTree = ""; }; + DD3AD31088110FDA73241B3581A2B2D7 /* FIRAuthStoredUserManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthStoredUserManager.m; path = FirebaseAuth/Sources/SystemService/FIRAuthStoredUserManager.m; sourceTree = ""; }; + DD6E7DB7F56371C9D91F90EC3F06B43D /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + DD9D94B4A4AE84B510828A2C92D89819 /* FPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPath.h; path = Firebase/Database/Core/Utilities/FPath.h; sourceTree = ""; }; + DDFD93E377D4D37AD058840107B807F3 /* FIRVerifyAssertionRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyAssertionRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h; sourceTree = ""; }; + DE0A7C68BE3AE4D9CF9E2C1E46DD5AC2 /* FIRDatabaseComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseComponent.h; path = Firebase/Database/Api/FIRDatabaseComponent.h; sourceTree = ""; }; + DE23FFEDE913A0F515A9DD8F1CF6D5DE /* FIRAuthDispatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthDispatcher.m; path = FirebaseAuth/Sources/Auth/FIRAuthDispatcher.m; sourceTree = ""; }; + DE334E8A8F2607F9F0CF675028E6CB9E /* FTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTree.m; path = Firebase/Database/Core/Utilities/FTree.m; sourceTree = ""; }; + DE3965AFA52554A33633B6C0264AAFB7 /* FBLPromise+Reduce.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Reduce.h"; path = "Sources/FBLPromises/include/FBLPromise+Reduce.h"; sourceTree = ""; }; + DE3C6C8B7895242C8B7E1A4EF84D3273 /* FAckUserWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAckUserWrite.h; path = Firebase/Database/Core/Operation/FAckUserWrite.h; sourceTree = ""; }; + DE8F826E478831E2D720397A11BCC6EA /* FIRMultiFactor+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRMultiFactor+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/FIRMultiFactor+Internal.h"; sourceTree = ""; }; + DEBA9D21F61A5BA2ED8516CD1A9AD43A /* GoogleDataTransportCCTSupport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransportCCTSupport-Info.plist"; sourceTree = ""; }; + DEBE75C4F3E332C7AB0A3A2FDAADE873 /* zh-Hant.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant.lproj"; sourceTree = ""; }; + DF010ADE9F5D95CEA7163C271DF4AF14 /* nanopb.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.debug.xcconfig; sourceTree = ""; }; + DF0342C0DE83E41409C0FC91022A091B /* FIRFinalizeMFAEnrollmentResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFinalizeMFAEnrollmentResponse.h; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRFinalizeMFAEnrollmentResponse.h; sourceTree = ""; }; + DF253DFDBF8A328A69C50E35AA66F7A9 /* GDTCORReachability.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORReachability.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m; sourceTree = ""; }; + DF33474F2924572E91E1E1B155DB0BE4 /* FViewCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewCache.m; path = Firebase/Database/Core/View/FViewCache.m; sourceTree = ""; }; + E04D809D94C88A8E91E01FA4F33D3DD4 /* es-GT.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-GT.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-GT.lproj"; sourceTree = ""; }; + E0621BC05ED00710FFB1A6F7DA1AE42A /* FBLPromise+Retry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Retry.m"; path = "Sources/FBLPromises/FBLPromise+Retry.m"; sourceTree = ""; }; + E0A5631CCB6A4F742557909BE284FBE0 /* pb_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_common.h; sourceTree = ""; }; + E0A693BC5175C7A316BEAA2AB79D1605 /* FirebaseCore-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCore-dummy.m"; sourceTree = ""; }; + E0C87CCE8B50E854B57AD5AA483FAA4A /* FUIInputTableViewCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; name = FUIInputTableViewCell.xib; path = Auth/FirebaseAuthUI/AccountManagement/FUIInputTableViewCell.xib; sourceTree = ""; }; + E0DAEAF751077AFB2147091AB7D8CEE8 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + E0E399D7C90DB8709C4D6B4C695505BB /* FIRDatabaseConfig_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig_Private.h; path = Firebase/Database/FIRDatabaseConfig_Private.h; sourceTree = ""; }; + E0EA93F03F796711CD33A8D1A75BE58E /* FIRPhoneAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRPhoneAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential.m; sourceTree = ""; }; + E127A35AD926485DF36164AB3C03700D /* FIRGetAccountInfoResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetAccountInfoResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoResponse.h; sourceTree = ""; }; + E1827EC28E1568C4E60FC36319763CBA /* FLimitedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLimitedFilter.h; path = Firebase/Database/Core/View/Filter/FLimitedFilter.h; sourceTree = ""; }; + E1D60FC645DFC56A7D6208D4B434C4F4 /* FAtomicNumber.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAtomicNumber.m; path = Firebase/Database/Utilities/FAtomicNumber.m; sourceTree = ""; }; + E20B04EEB401E2EA11B710895B87E3F2 /* skiplist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = skiplist.h; path = db/skiplist.h; sourceTree = ""; }; + E224F372FAC278DFD97371C8ADC9E6E8 /* FIRGitHubAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGitHubAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/GitHub/FIRGitHubAuthCredential.m; sourceTree = ""; }; + E23E05F6789EEAA15EACA16603FBC88A /* FIRAuthInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInterop.h; path = Interop/Auth/Public/FIRAuthInterop.h; sourceTree = ""; }; + E2A358A42E48E791E99164F4A01D034F /* FMaxNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMaxNode.h; path = Firebase/Database/FMaxNode.h; sourceTree = ""; }; + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCore.framework; path = FirebaseCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2DAC755661CCCACE7BA1813A316E3FA /* FUIAuthPickerViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUIAuthPickerViewController.m; path = Auth/FirebaseAuthUI/FUIAuthPickerViewController.m; sourceTree = ""; }; + E2E4137B3D3CF49006A9C9F46396C872 /* FIRAppAssociationRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppAssociationRegistration.h; path = FirebaseCore/Sources/FIRAppAssociationRegistration.h; sourceTree = ""; }; + E34AEFBD4E8EA4B3B004C94CAA3C78C1 /* FSyncPoint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncPoint.m; path = Firebase/Database/Core/FSyncPoint.m; sourceTree = ""; }; + E36DB6E3227A68055C28F6B1FC291F50 /* GTMKeychain_iOS.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMKeychain_iOS.m; path = Source/iOS/GTMKeychain_iOS.m; sourceTree = ""; }; + E3A8051121F638EC5568C79DAC199BA5 /* OIDTokenRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDTokenRequest.m; path = Source/AppAuthCore/OIDTokenRequest.m; sourceTree = ""; }; + E3B94329AF814460FDA387EC4AF66927 /* FIRResetPasswordResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRResetPasswordResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordResponse.m; sourceTree = ""; }; + E3D90122FAE5E38A814CFE89844E5604 /* FIRComponentContainerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainerInternal.h; path = FirebaseCore/Sources/FIRComponentContainerInternal.h; sourceTree = ""; }; + E40F8DC8B40272B99AAE3C0E3B49D1B5 /* GULNetworkConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkConstants.h; path = GoogleUtilities/Network/Private/GULNetworkConstants.h; sourceTree = ""; }; + E4F2A464610BC0BCA8327F2EFD71673D /* FBLPromise+Timeout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Timeout.m"; path = "Sources/FBLPromises/FBLPromise+Timeout.m"; sourceTree = ""; }; + E53A609A8D12173636B10864238813E6 /* FUIAccountSettingsOperationUpdateName.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAccountSettingsOperationUpdateName.h; path = Auth/FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperationUpdateName.h; sourceTree = ""; }; + E54A58182BF6AFB5DC13921079ACA542 /* es-PR.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PR.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-PR.lproj"; sourceTree = ""; }; + E5D4C62D339CFF2B64B65C4480F11094 /* FEventEmitter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventEmitter.m; path = Firebase/Database/Utilities/FEventEmitter.m; sourceTree = ""; }; + E61FAA8E21834BFFB167837F4917911E /* OIDAuthorizationRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDAuthorizationRequest.h; path = Source/AppAuthCore/OIDAuthorizationRequest.h; sourceTree = ""; }; + E62BA6BBCD5F0BB2FCD80BEF9750D13D /* FBLPromise+Catch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Catch.h"; path = "Sources/FBLPromises/include/FBLPromise+Catch.h"; sourceTree = ""; }; + E68A7082C16971B6E34E2B534C5CA9CF /* zh-Hant-TW.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "zh-Hant-TW.lproj"; path = "GoogleAuth/FirebaseGoogleAuthUI/Strings/zh-Hant-TW.lproj"; sourceTree = ""; }; + E6E77D4731AF3B4301FA924924F6AEE6 /* Pods-MyExperiences.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-MyExperiences.release.xcconfig"; sourceTree = ""; }; + E708ADE62264AB03AD82509CD7E587EF /* FServerValues.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FServerValues.h; path = Firebase/Database/Core/FServerValues.h; sourceTree = ""; }; + E7116A9977F9F821C626236E9AF7F5DA /* GDTCORFlatFileStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORFlatFileStorage.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORFlatFileStorage.h; sourceTree = ""; }; + E799655A87365710A1EB972B120BAE90 /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + E8697049410C51707EB215F2B6E1EEF7 /* FIRAuthProtoStartMFAPhoneResponseInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthProtoStartMFAPhoneResponseInfo.h; path = FirebaseAuth/Sources/Backend/RPC/Proto/Phone/FIRAuthProtoStartMFAPhoneResponseInfo.h; sourceTree = ""; }; + E8912EB183AA4629889505B7BB5CAB6F /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + E8F4C1D122F022ACE1D89ABFFF55CA0E /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + E92379D905E987E03974E31D4B6F3488 /* FirebaseUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseUI.release.xcconfig; sourceTree = ""; }; + E94487BBAAF18F4F350804E397EF0748 /* FIRInstallationsHTTPError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsHTTPError.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h; sourceTree = ""; }; + E94E0DEED20A943669F5DC4D7EE30AB7 /* FIREmailLinkSignInResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIREmailLinkSignInResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIREmailLinkSignInResponse.m; sourceTree = ""; }; + E9CC25C8A5F883C299D957961F94531D /* es-EC.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-EC.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-EC.lproj"; sourceTree = ""; }; + E9D51A261F16AF25D0F6D395165163D6 /* FIRSecureTokenResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSecureTokenResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSecureTokenResponse.h; sourceTree = ""; }; + EA086442AADF2F97230F5EE4868D00A3 /* OIDURLQueryComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDURLQueryComponent.m; path = Source/AppAuthCore/OIDURLQueryComponent.m; sourceTree = ""; }; + EA45E97075132BD1F9B6009A8CD150BD /* pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb.h; sourceTree = ""; }; + EAAE124D4FDC12A2A98D95D218A42E38 /* FOperationSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperationSource.h; path = Firebase/Database/Core/Operation/FOperationSource.h; sourceTree = ""; }; + EAB5C1025B15D6E3DC47C7BB0A984BC3 /* FIRDataSnapshot_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot_Private.h; path = Firebase/Database/Api/Private/FIRDataSnapshot_Private.h; sourceTree = ""; }; + EB2E4DBCB2D2FCA11BE0532ED759FF12 /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + EB2E6210777537A1E815E5BB3432D4CF /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + EB41C29425BE808F8982F4294DDD5D1E /* FIRInstallationsHTTPError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsHTTPError.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m; sourceTree = ""; }; + EB55F12741576DE36520DDEB0C6B041F /* GDTCORPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPlatform.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h; sourceTree = ""; }; + EB72BA1B95C57CA801DFED265DFC13D2 /* FIRStorageUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUtils.m; path = FirebaseStorage/Sources/FIRStorageUtils.m; sourceTree = ""; }; + EB9053EF1ABC9AAFACEFBF5649C58920 /* FTransformedEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTransformedEnumerator.h; path = Firebase/Database/FTransformedEnumerator.h; sourceTree = ""; }; + EB92407015693027CAA3FDAFA73D9004 /* FSnapshotUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotUtilities.m; path = Firebase/Database/Snapshot/FSnapshotUtilities.m; sourceTree = ""; }; + EC03F375BA39952863BFCD4DE1C9BCD3 /* FIRStorageUploadTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUploadTask.h; path = FirebaseStorage/Sources/Public/FIRStorageUploadTask.h; sourceTree = ""; }; + EC1A5D190A1FCAB42186925B0D8D9F53 /* FIRStorageListResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListResult.h; path = FirebaseStorage/Sources/Public/FIRStorageListResult.h; sourceTree = ""; }; + EC3E413A78DA754C0EC5E48FFCBE543F /* leveldb-library-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "leveldb-library-dummy.m"; sourceTree = ""; }; + EC9477E5C763D86BC2707DDA3A103547 /* FIRFacebookAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFacebookAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRFacebookAuthProvider.h; sourceTree = ""; }; + EC9A2EB346797982B9ADD669A3C48AF8 /* FTupleUserCallback.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleUserCallback.m; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.m; sourceTree = ""; }; + EC9F5D9D34F3AFD51FE48B10DCDAE1FD /* FTupleSetIdPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleSetIdPath.m; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m; sourceTree = ""; }; + ECA1431D8C20F0D81062BFD28CB77A98 /* GULReachabilityChecker+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULReachabilityChecker+Internal.h"; path = "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h"; sourceTree = ""; }; + ECB5A800627C88957FA98B1987378A64 /* merger.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = merger.cc; path = table/merger.cc; sourceTree = ""; }; + ED1556AF5E4C2B9B1D3F5307AB569547 /* env_posix_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_posix_test_helper.h; path = util/env_posix_test_helper.h; sourceTree = ""; }; + ED2CF6CBF8074DC1BD4979852C0F034F /* options.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = options.cc; path = util/options.cc; sourceTree = ""; }; + ED968492E27C084864021919F783D1FF /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + EDC8107A0FA008F847D143F5095FCA46 /* FBLPromise+Retry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Retry.h"; path = "Sources/FBLPromises/include/FBLPromise+Retry.h"; sourceTree = ""; }; + EE75160016ACEC2C076DE682CBFC27D7 /* OIDEndSessionRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDEndSessionRequest.m; path = Source/AppAuthCore/OIDEndSessionRequest.m; sourceTree = ""; }; + EE82A376F70C60AA9E73076A0E27ABB2 /* FIRMutableData_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData_Private.h; path = Firebase/Database/Api/Private/FIRMutableData_Private.h; sourceTree = ""; }; + EE8D1F47D22F1D6FAA6945CA508BFB12 /* FTreeSortedDictionaryEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionaryEnumerator.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h; sourceTree = ""; }; + EEF5CCBA93E845A4675A58E020BC2BC8 /* FIRStoragePath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStoragePath.m; path = FirebaseStorage/Sources/FIRStoragePath.m; sourceTree = ""; }; + EEF97A03248B0CEB94C0A83B2825E8E2 /* iterator_wrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator_wrapper.h; path = table/iterator_wrapper.h; sourceTree = ""; }; + EF27A4D04F2D6D69190C3B0E898A3BA0 /* es-MX.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-MX.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-MX.lproj"; sourceTree = ""; }; + EF2CE305347F3A55862365A41D0F7E5D /* AppAuth.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = AppAuth.modulemap; sourceTree = ""; }; + EF9FF3D787B018F3B85A15958455551A /* cct.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = cct.nanopb.c; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c; sourceTree = ""; }; + F00352F26052169EBFD33F59ECAD552D /* fa.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = fa.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/fa.lproj; sourceTree = ""; }; + F003A93336794A794BCBCD679CAE6F9C /* FIRServerValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRServerValue.h; path = Firebase/Database/Public/FIRServerValue.h; sourceTree = ""; }; + F01F346D4AD11A343B839A4C4244BB53 /* filter_policy.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_policy.cc; path = util/filter_policy.cc; sourceTree = ""; }; + F036049EC79DBAF2E473B1A9F7BF8D11 /* FIRStorageTokenAuthorizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTokenAuthorizer.m; path = FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m; sourceTree = ""; }; + F04402C3845EFFC388DEC264ED5CA75D /* FIRStorage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorage_Private.h; path = FirebaseStorage/Sources/FIRStorage_Private.h; sourceTree = ""; }; + F05F10A2D2CB88848EEE94089569B421 /* FIRDatabaseComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseComponent.m; path = Firebase/Database/Api/FIRDatabaseComponent.m; sourceTree = ""; }; + F060A463E10E778840180D47DF65B53C /* GTMMIMEDocument.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMMIMEDocument.m; path = Source/GTMMIMEDocument.m; sourceTree = ""; }; + F06F4E8D581CDEEFFC49BC1FC11DA980 /* FIRGetAccountInfoRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetAccountInfoRequest.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetAccountInfoRequest.m; sourceTree = ""; }; + F0E73FA2D08DB50ACE6FA0819B438E5D /* FIRAuthCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthCredential.m; path = FirebaseAuth/Sources/AuthProvider/FIRAuthCredential.m; sourceTree = ""; }; + F0EB221FC3A302A1F08E0A6AE9D192CC /* AppAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AppAuth.h; path = Source/AppAuth.h; sourceTree = ""; }; + F12D465A15972386FC714191DB492F6C /* ru.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = ru.lproj; path = Auth/FirebaseAuthUI/Strings/ru.lproj; sourceTree = ""; }; + F14BBD6EFFD126F1D545DD56A2CC772E /* ic_google.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_google.png; path = GoogleAuth/FirebaseGoogleAuthUI/Resources/ic_google.png; sourceTree = ""; }; + F156EBA03AB88203E99DFE8B8BA46A02 /* nl.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = nl.lproj; path = Auth/FirebaseAuthUI/Strings/nl.lproj; sourceTree = ""; }; + F1A95286B9447DB591D70DF43B8B09E6 /* FIRGetProjectConfigResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGetProjectConfigResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.h; sourceTree = ""; }; + F1D52AFE6BB5A995128447A1AF90B5D1 /* FTupleFirebase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleFirebase.m; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.m; sourceTree = ""; }; + F2036DCCF9E03B57FE8FFCC80F813155 /* es-HN.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-HN.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-HN.lproj"; sourceTree = ""; }; + F23F6A10C23DA53CA0245A145EF508AD /* FNextPushId.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNextPushId.m; path = Firebase/Database/Utilities/FNextPushId.m; sourceTree = ""; }; + F26BE0CF90BD08FB506A58DF1E66DFAC /* FIRAuthErrorUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthErrorUtils.h; path = FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h; sourceTree = ""; }; + F26FF619FBA8F5E01A361CF0C1860F6B /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + F28F293116C24E8DF57B232A6D217EBF /* block_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block_builder.cc; path = table/block_builder.cc; sourceTree = ""; }; + F2AF2A78A3B183DE0016FB7675B21129 /* FIRComponentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentType.m; path = FirebaseCore/Sources/FIRComponentType.m; sourceTree = ""; }; + F31501F6FF6000C04AC321C6A82873AB /* FirebaseDatabase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseDatabase.release.xcconfig; sourceTree = ""; }; + F31F9DA1BF7C971697A98B2825B32A75 /* OIDEndSessionResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OIDEndSessionResponse.h; path = Source/AppAuthCore/OIDEndSessionResponse.h; sourceTree = ""; }; + F379CEF3D2BB9681071028E02F1BD578 /* FIRDatabase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabase.m; path = Firebase/Database/Api/FIRDatabase.m; sourceTree = ""; }; + F3DF5AF9462B5AC7A7232B374178407B /* GDTCORFlatFileStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORFlatFileStorage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORFlatFileStorage.m; sourceTree = ""; }; + F3F37DC0D68E2ACE25E446599F0A6124 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + F3F5B906825D61484CAAA87789BD98D5 /* leveldb-library.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "leveldb-library.release.xcconfig"; sourceTree = ""; }; + F405BDCCD96FE6F1912403A62DAE2B04 /* leveldb-library.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "leveldb-library.debug.xcconfig"; sourceTree = ""; }; + F451879A1A9A3D5704CEC1CA6EF6F24B /* FBLPromise+Await.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Await.m"; path = "Sources/FBLPromises/FBLPromise+Await.m"; sourceTree = ""; }; + F4CAD44EEAACE1ED06ACA9EE0BA5A69A /* tr.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = tr.lproj; path = Auth/FirebaseAuthUI/Strings/tr.lproj; sourceTree = ""; }; + F514CF18463C2B267F4B21CE743FC308 /* GDTCOREvent+GDTCCTSupport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GDTCOREvent+GDTCCTSupport.h"; path = "GoogleDataTransportCCTSupport/GDTCCTLibrary/Public/GDTCOREvent+GDTCCTSupport.h"; sourceTree = ""; }; + F54FB7D1F60007DA1DA644E4C0BF61F4 /* block_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block_builder.h; path = table/block_builder.h; sourceTree = ""; }; + F571E596E02E04A50AD81E7326931D0C /* he.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = he.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/he.lproj; sourceTree = ""; }; + F59468EA40FA729BFE3CD9A8006CFBEE /* table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table.h; path = include/leveldb/table.h; sourceTree = ""; }; + F64CE77C106A717D67E4CDE515D39305 /* FIRInstallationsStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStatus.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h; sourceTree = ""; }; + F6C0E7581284480F32192794A5A25698 /* OIDServiceConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OIDServiceConfiguration.m; path = Source/AppAuthCore/OIDServiceConfiguration.m; sourceTree = ""; }; + F723B27C6E94B8411EC2A203BC352B35 /* FIRStorageConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageConstants.m; path = FirebaseStorage/Sources/FIRStorageConstants.m; sourceTree = ""; }; + F72E90BEC7A0042936C7066EFF232E52 /* leveldb-library.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "leveldb-library.modulemap"; sourceTree = ""; }; + F74DEF883FF6125F49131BC4DF11C125 /* GDTCORUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploader.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h; sourceTree = ""; }; + F77B33F5B4224F35E3F624BE59553B38 /* FIRStorageDeleteTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDeleteTask.h; path = FirebaseStorage/Sources/FIRStorageDeleteTask.h; sourceTree = ""; }; + F7FAB3E24D105A6595C0A0EFA8B1674F /* FIRStorageComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageComponent.m; path = FirebaseStorage/Sources/FIRStorageComponent.m; sourceTree = ""; }; + F7FD5A9390F75691B9442F5ADA1BA075 /* GDTCOREvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCOREvent.m; path = GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m; sourceTree = ""; }; + F816F516E077044050B35F73606B9143 /* GTMSessionFetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcher.h; path = Source/GTMSessionFetcher.h; sourceTree = ""; }; + F8267B5FBB4E05B085FAA667C3AE0B4E /* write_batch_internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch_internal.h; path = db/write_batch_internal.h; sourceTree = ""; }; + F854F0655C7BC1A52D8C680D1EDEF4CA /* es-PE.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = "es-PE.lproj"; path = "Auth/FirebaseAuthUI/Strings/es-PE.lproj"; sourceTree = ""; }; + F8733E756435BEDCF24F263A778E0ECC /* FIRFederatedAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRFederatedAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRFederatedAuthProvider.h; sourceTree = ""; }; + F8A44483BAAFA67830C281FFEDC4CA4B /* FirebaseInstallations.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstallations.modulemap; sourceTree = ""; }; + F8B0B924EF0FBA3293977F67BC3ADB6A /* FBLPromise+Wrap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Wrap.h"; path = "Sources/FBLPromises/include/FBLPromise+Wrap.h"; sourceTree = ""; }; + F8FA12F53A842731E91E4E2D261613DD /* FIRAuthAppCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthAppCredential.h; path = FirebaseAuth/Sources/SystemService/FIRAuthAppCredential.h; sourceTree = ""; }; + F909B1A1A39DA32987EB786BA0FF883E /* FIRAuthAPNSToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAuthAPNSToken.m; path = FirebaseAuth/Sources/SystemService/FIRAuthAPNSToken.m; sourceTree = ""; }; + F98BAF8C84B54154210F7ACBE4D637A0 /* FIRCreateAuthURIRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCreateAuthURIRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h; sourceTree = ""; }; + F998DA016600AADC4C4757203652294C /* FIRVerifyClientResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVerifyClientResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRVerifyClientResponse.h; sourceTree = ""; }; + F9C18C1536C6548F5BB3AE6687B9A6CA /* FIRDeleteAccountResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDeleteAccountResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRDeleteAccountResponse.m; sourceTree = ""; }; + FA08C3D52F16A1EC004CAC114EAB689F /* FIRAuthBackend.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthBackend.h; path = FirebaseAuth/Sources/Backend/FIRAuthBackend.h; sourceTree = ""; }; + FA0BE7E74ED2EBA52D88C5CDED4BAA14 /* FIRResetPasswordRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRResetPasswordRequest.h; path = FirebaseAuth/Sources/Backend/RPC/FIRResetPasswordRequest.h; sourceTree = ""; }; + FA139674819FBA9C94F5375AC3D9C06D /* GDTCORTransport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransport.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m; sourceTree = ""; }; + FA544CBD59A051B4A85F775980536364 /* FirebaseCore.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCore.modulemap; sourceTree = ""; }; + FA971777AE9035EA63091527E76D1AF1 /* FSparseSnapshotTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSparseSnapshotTree.h; path = Firebase/Database/Core/FSparseSnapshotTree.h; sourceTree = ""; }; + FACDEAFE27619DEF3D9C6BEBD477202C /* bg.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = bg.lproj; path = GoogleAuth/FirebaseGoogleAuthUI/Strings/bg.lproj; sourceTree = ""; }; + FB35D2B3E2A95345454CCC31127AFA58 /* FIRStartMFAEnrollmentRequest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStartMFAEnrollmentRequest.m; path = FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll/FIRStartMFAEnrollmentRequest.m; sourceTree = ""; }; + FB67B500FD9B4600EC2F304EFDA38590 /* testharness.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = testharness.cc; path = util/testharness.cc; sourceTree = ""; }; + FB9F8446BA7A0A522EE8B2B922D07A7A /* firebasecore.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = firebasecore.nanopb.c; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c; sourceTree = ""; }; + FBC075A76606AA21175616AD5D5A2818 /* GDTCOREvent+GDTCCTSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GDTCOREvent+GDTCCTSupport.m"; path = "GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCOREvent+GDTCCTSupport.m"; sourceTree = ""; }; + FC0ADC33764603966493C028E141A96C /* FIRSendVerificationCodeResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSendVerificationCodeResponse.h; path = FirebaseAuth/Sources/Backend/RPC/FIRSendVerificationCodeResponse.h; sourceTree = ""; }; + FC0EA04586CCBCCD2808FC6B7762C4C0 /* FIRGetProjectConfigResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRGetProjectConfigResponse.m; path = FirebaseAuth/Sources/Backend/RPC/FIRGetProjectConfigResponse.m; sourceTree = ""; }; + FC0FDCC1AA88D683B0D4E35474D6DE84 /* FIRPhoneMultiFactorInfo+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRPhoneMultiFactorInfo+Internal.h"; path = "FirebaseAuth/Sources/MultiFactor/Phone/FIRPhoneMultiFactorInfo+Internal.h"; sourceTree = ""; }; + FC2A2B517E03A8347DD866AB5D8629EC /* GTMSessionFetcherService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcherService.m; path = Source/GTMSessionFetcherService.m; sourceTree = ""; }; + FC5C52298AD31598C0A44EF9B2C6F44C /* FIRDatabaseReference_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseReference_Private.h; sourceTree = ""; }; + FC7E3FA7EA5372B5C2C86F26E4BE5033 /* FPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPath.m; path = Firebase/Database/Core/Utilities/FPath.m; sourceTree = ""; }; + FCFAA95BB50A7A1D10B42814FAE412EE /* FCompoundWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundWrite.m; path = Firebase/Database/Snapshot/FCompoundWrite.m; sourceTree = ""; }; + FD4A9A5E7A8A9588DF99DB175B94644E /* FirebaseInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstallations.h; path = FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h; sourceTree = ""; }; + FD8A4AC55991A3986691EF3AC1B9D012 /* FIRGameCenterAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRGameCenterAuthProvider.h; path = FirebaseAuth/Sources/Public/FIRGameCenterAuthProvider.h; sourceTree = ""; }; + FDBB301A94F6610BADD69F289B58408A /* FIRInstallationsAPIService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAPIService.m; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m; sourceTree = ""; }; + FE43939DA337EF2714620503CF0ABD71 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + FE6DF75AC07EAEEFBBE8B2D16DA1929E /* FUIAuth.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuth.h; path = Auth/FirebaseAuthUI/FUIAuth.h; sourceTree = ""; }; + FE7B98B1A5BFC14EF81EFCD319A7C848 /* el.lproj */ = {isa = PBXFileReference; includeInIndex = 1; name = el.lproj; path = Auth/FirebaseAuthUI/Strings/el.lproj; sourceTree = ""; }; + FF280DA876648901D57970E5E26947C0 /* FUIAuthStrings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUIAuthStrings.h; path = Auth/FirebaseAuthUI/FUIAuthStrings.h; sourceTree = ""; }; + FF680DFC00216365C48B4199252AEB01 /* FPruneForest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPruneForest.m; path = Firebase/Database/Persistence/FPruneForest.m; sourceTree = ""; }; + FF8F5D3FDDBE05A714D93F601CAFB9A6 /* FIRAuthRPCResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthRPCResponse.h; path = FirebaseAuth/Sources/Backend/FIRAuthRPCResponse.h; sourceTree = ""; }; + FFA39FBA8960A7E7D4BE2CB4087A52A9 /* log_format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_format.h; path = db/log_format.h; sourceTree = ""; }; + FFE5D5FAFCA8CD85996CACEF15BA5467 /* FIREmailAuthProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIREmailAuthProvider.h; path = FirebaseAuth/Sources/Public/FIREmailAuthProvider.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0AFE9A74FD29F7DE5D5FB75D8ADCADD9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E5D7F12887D02AB5D3E9AFAD1726FF76 /* FBLPromises.framework in Frameworks */, + 90E7FFB1CDA02508DE000111BABF9454 /* Foundation.framework in Frameworks */, + 45E5ACFE303C1B6358F8C7E9511A6386 /* Security.framework in Frameworks */, + 568276FDBFC7923067446270D62B39CB /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0B65A1B0CBA6A62115EC026D09D52C67 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DAC538082C4126C06C1BFE1C9A257981 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 16CF22217BEA907AC6550A5C485822F1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 71BCEC30B9A618753E543ED8C606B9F8 /* Foundation.framework in Frameworks */, + EF92363675B8414D14801D29A288FA31 /* SafariServices.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 288EB6573D0226789F0BDCD82D886C6F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3534B7679EAF6E73DD83126C1EF852DC /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A50BBBB67ED88BFDFCF280534A2E913 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A80F4FE31E9C5E7397DD7E457639C91F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 307F3A574328AD48FA2EC0FEAF73B536 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6BF3AD3CA039D7802D2E3C66001461A3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1EF49485D4256AE152524C1FB5DEA4 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 771934A8292F9E56AF16AD9C444EFBBE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6B51E4E5D5B08C3E33B06C2AFAC81B01 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 82A44DCD4F9E83CF41B5F67761A3A661 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E5BEA8D45FA0FF2DF302A9608B9BF67E /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8527AD5C6F1EE04394A63A6D7529F155 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E1D083BEA9134178F042CDFCFC19B6ED /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9145DBFE6D975B79CD63546350269025 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B9DFB07597C2F67EBE4AFFEA69DE617F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9AABEF3517D06D364480F0EAD6AA38FB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F59EBF58D2C5254E95E44135A99D1012 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9965926B4060D881F8C257FBF691E4F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 217240440770FB45A9B77027674F477B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AD8BF722AF274344DDFA95F92F76B092 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CA9D5CCB80E9B6BBE4FA9901D84A22FA /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C07D9F3989267B68F049F291CF9288C5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F7C22DF3F17C92D62C2E2B3FC509BCBA /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C4750097903995BD1C45CD8DEA358160 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D10EA948D710666D30B4D6C80EF714F8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BC76DCB86613935CF0F4D01BD1C95C54 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E980906BBCCA56251CEB7CC0D2D4C47B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0200AA2050195591B45B63AC85881913 /* AppAuth.framework in Frameworks */, + CD8B0139FF974740C64897277783C36E /* Foundation.framework in Frameworks */, + 848D22C317E754C83F8B7747E07CB1C1 /* GTMSessionFetcher.framework in Frameworks */, + 5588AB3DE0541FF7D1BD89B8DAE0419C /* SafariServices.framework in Frameworks */, + AE0D2748DD86501DFA486CE10616CDF8 /* Security.framework in Frameworks */, + D8450B6C370059F67789E7EC71A2981C /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EF7F5A1366D52D41CFEE3FF47BCD96E2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EEBEE12CF7A3B76897339AEBF82DBA9A /* Foundation.framework in Frameworks */, + E2DB411F4F19E4999A6994BE078B24EB /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 010961E11244E5A8FB7D5801285A62E8 /* iOS */ = { + isa = PBXGroup; + children = ( + A902EC22E4E7592D1507079756376044 /* Foundation.framework */, + C74BB36833DAE2734F5679B8EE2E04FD /* SafariServices.framework */, + 5E942549C86F57C477E3AC759C80C513 /* Security.framework */, + AEC5BAE613C9C504615D4DFD6BA5F32E /* SystemConfiguration.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 019E979A0BD29BD5BE26961DB955B9E0 /* Firebase */ = { + isa = PBXGroup; + children = ( + 5B199D50257EA2B47977DE95F642803A /* CoreOnly */, + 992BEF555EDF920C929910AF6D14080F /* Support Files */, + ); + name = Firebase; + path = Firebase; + sourceTree = ""; + }; + 04B623AC022CECE0EEA39898BA767119 /* Support Files */ = { + isa = PBXGroup; + children = ( + A99030435F8DB28FCCE7B7B4819BB6C5 /* GoogleSignIn.debug.xcconfig */, + A43B99F4F9A7AFE85D8AC61C327BA44C /* GoogleSignIn.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleSignIn"; + sourceTree = ""; + }; + 0DED8E1D95D61E4D5C5C4DC1454FF079 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 249F2A82CBC0749A828D61764B441E28 /* AppAuth.framework */, + 3097FE693219B2669E5404BF817BDBB3 /* FBLPromises.framework */, + 8BFC8863CD88E6BCE4F75A47B49C31FA /* GTMSessionFetcher.framework */, + 010961E11244E5A8FB7D5801285A62E8 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0F6C9DDC3A7409D759418E33B0EDE0DE /* Support Files */ = { + isa = PBXGroup; + children = ( + 9D19FDA9CE8895E11678DDCB7526EF93 /* GoogleAppMeasurement.debug.xcconfig */, + 24C633FD22C7C3FC566586ADA13E5100 /* GoogleAppMeasurement.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleAppMeasurement"; + sourceTree = ""; + }; + 107E41B29C1C3C9658E3185F9CD1576D /* GTMSessionFetcher */ = { + isa = PBXGroup; + children = ( + 89569272841C0FF05B46467EF195732C /* Core */, + F3435E6BF052FF25BDEDE5786AE030B0 /* Full */, + 8789451A1D0C09E582670C9DC247F6A5 /* Support Files */, + ); + name = GTMSessionFetcher; + path = GTMSessionFetcher; + sourceTree = ""; + }; + 147DB21F2D8647751EAFCF3213D751A5 /* Products */ = { + isa = PBXGroup; + children = ( + 3FD1B4C1246D643E9476438C28048FA8 /* AppAuth.framework */, + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */, + 43B1E4CD7B30B9FD278100133C2AC788 /* FirebaseAuth.framework */, + A3BA8163828042C7132F40FBC25E24D5 /* FirebaseAuthUI.bundle */, + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */, + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */, + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */, + CE49BDFC8463EC230FD4E8C9B3385281 /* FirebaseGoogleAuthUI.bundle */, + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */, + 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */, + 62F454249D6AA95C313D27B86A06B4F4 /* FirebaseUI.framework */, + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */, + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */, + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */, + 6FD122EA0AB9AB2A8FFA5F676C795DF0 /* GTMAppAuth.framework */, + C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */, + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */, + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */, + 25BE0E179757406561E2975B3099D56C /* Pods_MyExperiences.framework */, + ); + name = Products; + sourceTree = ""; + }; + 1753BD617404E97A20DC88ADA9F83561 /* decode */ = { + isa = PBXGroup; + children = ( + ); + name = decode; + sourceTree = ""; + }; + 1E1910FE64FF8B78D45F08571A70EE6B /* nanopb */ = { + isa = PBXGroup; + children = ( + EA45E97075132BD1F9B6009A8CD150BD /* pb.h */, + 5119B34C2C5AA2AE16AE4B3BA48C5532 /* pb_common.c */, + E0A5631CCB6A4F742557909BE284FBE0 /* pb_common.h */, + A59B1CF1D3E7FC2F9080D57916333E55 /* pb_decode.c */, + 792D76D6241F70B08F7CAD7ADB1D72E2 /* pb_decode.h */, + 3082E6493AB93A9C2593DFF6F5506755 /* pb_encode.c */, + 2D00A435DFB725951078FD373898E52A /* pb_encode.h */, + 1753BD617404E97A20DC88ADA9F83561 /* decode */, + 87EC8C2EB82B82E132A012528AFC0AB8 /* encode */, + ED459BF38D565AB1D5FCF41ACA3909FB /* Support Files */, + ); + name = nanopb; + path = nanopb; + sourceTree = ""; + }; + 1F87FC372EF5BD730F3C2367FCF82A09 /* Resources */ = { + isa = PBXGroup; + children = ( + 444161411F02B826835C81A17C1E4285 /* ar.lproj */, + FACDEAFE27619DEF3D9C6BEBD477202C /* bg.lproj */, + BDF69634B5F3A7C722770C9FA296E0B7 /* bn.lproj */, + 0098C77A2AF070A9DED76E3055458A8C /* ca.lproj */, + 05FBF2C6D14E46A75180F9E7C78B1A5E /* cs.lproj */, + 40BE96E1BFC9CE018C8D910E77FE05E1 /* da.lproj */, + 03AC94CC3669CD2F4343DCD28A98153B /* de.lproj */, + 04FD97AE67C10679D659B68EFCB64697 /* de-AT.lproj */, + 1EF65A483BB4A3FD7205F21724439323 /* de-CH.lproj */, + 79A12CF03274F6EAB14327C8ADDDC0DA /* el.lproj */, + B9DB9D346A7C30019219602974216E5C /* en.lproj */, + 46537E48C5450772F4B264F790FD1694 /* en-AU.lproj */, + AF07CF05D98104373FD3D96B8260E436 /* en-CA.lproj */, + 76C514358FDBBCF9A559BE493725B973 /* en-GB.lproj */, + B10154179A246D8D0A16DC1C08225929 /* en-IE.lproj */, + 97031F647363FF54D7E0D14B833CB369 /* en-IN.lproj */, + A6A2A48DDBA7CD20E2D170FF98D7D6E2 /* en-SG.lproj */, + 6024FDADF987F2A905E3FABFDCA3FAD1 /* en-ZA.lproj */, + 5E2CA4028042B0790AE59AB6B90E6E8C /* es.lproj */, + 1A2746E30564EC71904AB662184CD169 /* es-419.lproj */, + 3BCF2E04232FF1193F3C043072D64FF8 /* es-AR.lproj */, + 6B74182157734B3092D8EFAF015E4B26 /* es-BO.lproj */, + 23C82953FC80B9C61F784D4B27E54E19 /* es-CL.lproj */, + 1CD458A32FF2A6B04A8196DCD333D719 /* es-CO.lproj */, + 42914413BA6F0875F89E6B59303ACC41 /* es-CR.lproj */, + 74A4644D82340D84377819E6EFA115CC /* es-DO.lproj */, + 40F945E679A09218AE09F90EED9F4FA2 /* es-EC.lproj */, + 4A4CBF036EE62FFEBB150AB9227C0939 /* es-GT.lproj */, + CB8FE127E94323EA8191DC5075AED4FE /* es-HN.lproj */, + 77EC7724051F1C393F7400C9463218FA /* es-MX.lproj */, + 76A00F380F7CB86BC5ABAB18B8C3C512 /* es-NI.lproj */, + 16222C91E613CBB3BA3B1594E89FD7D7 /* es-PA.lproj */, + 3AB38AF65C51703D0C443B947C88594F /* es-PE.lproj */, + 8AA74947BFD3B18B07530AB29E37CB2B /* es-PR.lproj */, + B530A33CA1805EF305BEC939BCCF6E7D /* es-PY.lproj */, + 49F63393A9E80EBBF65F56B5EDB54614 /* es-SV.lproj */, + BBC868C8D7509594738EB3FF2E0097AF /* es-US.lproj */, + DCF3B50D1BFBD7F6BA12307093BA9BD2 /* es-UY.lproj */, + 23D196E2657D5CF6B7EEEA795134088B /* es-VE.lproj */, + F00352F26052169EBFD33F59ECAD552D /* fa.lproj */, + 60470DBAAA6781680A41419A079C8788 /* fi.lproj */, + A77908716A340BFE5D8D34EE22B8A578 /* fil.lproj */, + 16296FC7FAD4F7911C51F68AFD78E15F /* fr.lproj */, + 0F53635464E43DABB555A566F5EE35DB /* fr-CH.lproj */, + 160F9D533A4A53571BA6D1E2172D1F0C /* gsw.lproj */, + 0C6ED211312B3541D9CED14186669579 /* gu.lproj */, + F571E596E02E04A50AD81E7326931D0C /* he.lproj */, + 78A548A17202BBEBCAD3914415FA6185 /* hi.lproj */, + 5A0D953E59A8DED28D3164EC06E93905 /* hr.lproj */, + 4C33F929C488C2621B9F88ED675801ED /* hu.lproj */, + F14BBD6EFFD126F1D545DD56A2CC772E /* ic_google.png */, + 17A216C406500454DF05929B98E58410 /* ic_google@2x.png */, + D32F42267B26545CE5E602067ACDC089 /* ic_google@3x.png */, + BEE24FC0665340E787AA4D29456F0DE1 /* id.lproj */, + 78E128753A283DBACD262E6F97C1D738 /* it.lproj */, + BC2B894E2BDEB2C236F169221286AD5B /* ja.lproj */, + 3795D22043104C7331249E54D65FDCBD /* kn.lproj */, + 431F138349D4FE38FA96998F33938388 /* ko.lproj */, + CD681182A0A791D44FA0677AAFE46C33 /* ln.lproj */, + 80E00FBA13DD98479E065206F43AB591 /* lt.lproj */, + 187318BA2B8C87BF94F4551700E3363D /* lv.lproj */, + 9A23A0C9B7AC4E516824E1155565BF31 /* mr.lproj */, + C3671B246F2292948552AA5DC9D688A0 /* ms.lproj */, + A791424A89A3CDA5752E45E7C544B668 /* nb.lproj */, + 01319D0532FDE21A1DAB1F8E6E5716CE /* nl.lproj */, + 20EABA71D9A42FBE54F15ED4D7A36D2C /* nn-NO.lproj */, + 0534AAF51A65ACC6357CCDC6F5B9A17A /* pl.lproj */, + 0676931B0B675CD8006C8315CEDA9D2D /* pt.lproj */, + 0735B2D4D87BB62774F7B9557FBF231F /* pt-BR.lproj */, + 752204D20D33393B7F9DFE09AC0A6117 /* pt-PT.lproj */, + 190DF118BCA465ED356FCBBE1176A561 /* ro.lproj */, + 03C4883C10FF5038DF368CDEDE4218B7 /* ru.lproj */, + 45C09F6B2C40752E3427CB95ECEC8ACC /* sk.lproj */, + C457F92BE0D82B39FB3D3302C73322C8 /* sl.lproj */, + 796D52C9F909C41144190320EC3D42ED /* sr.lproj */, + 8458CF3753249A59F6F220A43276CADE /* sr-Latn.lproj */, + 4BD64D667BE6E644D010A4C6AB245206 /* sv.lproj */, + 04D93189E444EF105CE4F9D654BE2315 /* ta.lproj */, + 68C7EA4DCAD33358C682613FB0CDF819 /* th.lproj */, + 0DF00E0B4050F287AF4F7EF1D9D3520D /* tr.lproj */, + BE57096B74561E4E5589CC94B228D138 /* uk.lproj */, + 8EAB0E19E6BFAE72A24B17CDAE58272E /* ur.lproj */, + 002837788CEDF728C9F8B00AE09AF35E /* vi.lproj */, + 77428BF49AAD71B811C8A6049C09E441 /* zh.lproj */, + 9C11205E4D4588C7ABA50978488F6849 /* zh-Hans.lproj */, + DEBE75C4F3E332C7AB0A3A2FDAADE873 /* zh-Hant.lproj */, + E68A7082C16971B6E34E2B534C5CA9CF /* zh-Hant-TW.lproj */, + ); + name = Resources; + sourceTree = ""; + }; + 2712AD7DB88E460F312299F7F7F70881 /* ExternalUserAgent */ = { + isa = PBXGroup; + children = ( + F0EB221FC3A302A1F08E0A6AE9D192CC /* AppAuth.h */, + 3739C5F655F31DED05B46617ABCB9412 /* OIDAuthorizationService+IOS.h */, + 6080376A14E37CCAB6B3B0C2BA0D0855 /* OIDAuthorizationService+IOS.m */, + 16B53E64756CED682CA2F191367C5A91 /* OIDAuthState+IOS.h */, + 58C160DA81101F1D0015E334D29C329E /* OIDAuthState+IOS.m */, + B780FFAC1852977D9C50DEB819B56185 /* OIDExternalUserAgentCatalyst.h */, + 68C90E3FDA5545E6FD31403207BF27DC /* OIDExternalUserAgentCatalyst.m */, + 0BEA2C64BB6137F4C8D76D2555CD2590 /* OIDExternalUserAgentIOS.h */, + 332B6F1DCD90DD0A9FABF2C8718B4F0B /* OIDExternalUserAgentIOS.m */, + D821A20F4F239BB23077D1E020CD4F02 /* OIDExternalUserAgentIOSCustomBrowser.h */, + 4D79E78D7503509C5FB9CECC26794CC1 /* OIDExternalUserAgentIOSCustomBrowser.m */, + ); + name = ExternalUserAgent; + sourceTree = ""; + }; + 28A550D67DF0EA2F2C0578DDF7F7AA0F /* Environment */ = { + isa = PBXGroup; + children = ( + 4F2E84C3E82B88B41FC14399D96AFF7E /* GULAppEnvironmentUtil.h */, + 634E60D54FACAEA3CDD23BC456EB97E0 /* GULAppEnvironmentUtil.m */, + B7FE9445781AA6E6E3D1ECB979847E15 /* GULHeartbeatDateStorage.h */, + CFD98378F7C00DB91E8F99CDD3B231A9 /* GULHeartbeatDateStorage.m */, + C9F72563209A23CBD0D09F13E342C5F8 /* GULKeychainStorage.h */, + 0353E7DD4FD4E16ACEFB53AC1DDFAC78 /* GULKeychainStorage.m */, + 6259D501189F90B7AE0391DF9109BD35 /* GULKeychainUtils.h */, + 4E24B05160E278D466B32F147A97FE68 /* GULKeychainUtils.m */, + C6F70D4FA6DDFC1F1BE8ADAF97E4F5DF /* GULSecureCoding.h */, + 0889F6ED1E26D93D3A5813350CCC106E /* GULSecureCoding.m */, + ); + name = Environment; + sourceTree = ""; + }; + 29CB7B36A9770799F2CB78484DF627FA /* FirebaseStorage */ = { + isa = PBXGroup; + children = ( + 17D499F429E7B17807816EF3C2257723 /* FIRAppInternal.h */, + CDB74299006EB164009D493442C606F5 /* FIRAuthInterop.h */, + 20070732AC1D13563706D375942B5198 /* FIRComponent.h */, + 61FECAF9DDCFEB0AAC6EB34E1F4E9795 /* FIRComponentContainer.h */, + 82FB7E4D042D8701D3495BC636CF8FAC /* FIRComponentType.h */, + F26FF619FBA8F5E01A361CF0C1860F6B /* FIRCoreDiagnosticsConnector.h */, + 8A48AB5E3FB50C36BA0EC0B20B809C21 /* FIRDependency.h */, + 6354B7053086BB30B515EDE313EB0572 /* FirebaseCoreInternal.h */, + 09A097B832C0A5236DD3C244CE58A25C /* FirebaseStorage.h */, + 0C79891D26C39DACEE62796D724DBFCE /* FIRErrorCode.h */, + EB2E4DBCB2D2FCA11BE0532ED759FF12 /* FIRErrors.h */, + 618B1E5DFBEC073ABD03719A3CBEC5A2 /* FIRHeartbeatInfo.h */, + 9F70E4BE2CF979D01CD0A2A2CC576453 /* FIRLibrary.h */, + 0B2F5E8C7D0001EC52275D753C23D8D0 /* FIRLogger.h */, + 327D01056854E2B13B40561F172984A5 /* FIROptionsInternal.h */, + 8C8947AB7BD466CCB237F6F4D68045B0 /* FIRStorage.h */, + 3EA0C271CB77739BABDAAFE7F7636239 /* FIRStorage.m */, + F04402C3845EFFC388DEC264ED5CA75D /* FIRStorage_Private.h */, + BF2AEE9791F5228164E2A159B584198C /* FIRStorageComponent.h */, + F7FAB3E24D105A6595C0A0EFA8B1674F /* FIRStorageComponent.m */, + 1B85E94CC4133DE93C8AB2185EB576E2 /* FIRStorageConstants.h */, + F723B27C6E94B8411EC2A203BC352B35 /* FIRStorageConstants.m */, + 7B0AD5E6656068EFD990FF19F45F0202 /* FIRStorageConstants_Private.h */, + F77B33F5B4224F35E3F624BE59553B38 /* FIRStorageDeleteTask.h */, + 76C1B95C2C3697B27A7E6D35B1471E75 /* FIRStorageDeleteTask.m */, + CBA6A06C975D6C6C939DB4CB58EF49F8 /* FIRStorageDownloadTask.h */, + 5EFF3A22F1C48B4980A4B052C0875FD6 /* FIRStorageDownloadTask.m */, + C40D486D4F445531BAB7739A5F3D2AF6 /* FIRStorageDownloadTask_Private.h */, + 71548566AA12411F1169B351463A8EF1 /* FIRStorageErrors.h */, + 3A44B8B2E53063933C325653CE73494F /* FIRStorageErrors.m */, + 9C5E6C966427FB61A02E3C1DA552D236 /* FIRStorageGetDownloadURLTask.h */, + 3A3B1BAC7E72143AD4BA76261839C839 /* FIRStorageGetDownloadURLTask.m */, + 218384F9184D07D0CC75E9E2D849833E /* FIRStorageGetDownloadURLTask_Private.h */, + 02A0E580086D035BB4EC4EFA878CAC1D /* FIRStorageGetMetadataTask.h */, + 370DC54124A24E6D2D89067F66C8807D /* FIRStorageGetMetadataTask.m */, + EC1A5D190A1FCAB42186925B0D8D9F53 /* FIRStorageListResult.h */, + 2707F538B792760E9D23053698344742 /* FIRStorageListResult.m */, + 3B88E94C33408BA3A4273682782F14A5 /* FIRStorageListResult_Private.h */, + D18899BE4BC7E2D4F952DB97896F1A68 /* FIRStorageListTask.h */, + 1CE5CAD485E3BB64ADEA5F812EAD1AFF /* FIRStorageListTask.m */, + 3D664A23B168D6D45A0115AFEAB24697 /* FIRStorageMetadata.h */, + 2BED935E00DCA51EE1CBD631ED2DE24E /* FIRStorageMetadata.m */, + 5AD0170E1AE017F7BF65280EE7A9D1B5 /* FIRStorageMetadata_Private.h */, + 8CFBC168B85EA71F74E6C24C03FDCA9D /* FIRStorageObservableTask.h */, + 33AF2BEA19AA92B905791B5D2A1C4AF7 /* FIRStorageObservableTask.m */, + 4FD4FE57FB9B916510FB562EE2A4BE10 /* FIRStorageObservableTask_Private.h */, + B213F5865A99165D7CD215C45D137240 /* FIRStoragePath.h */, + EEF5CCBA93E845A4675A58E020BC2BC8 /* FIRStoragePath.m */, + D79C916C4A7F1CD706F33D10361AD2A1 /* FIRStorageReference.h */, + 13D66A61C6F8FE04AD5A3BADADA1656D /* FIRStorageReference.m */, + 278BB3E5433817C52237810200BD9406 /* FIRStorageReference_Private.h */, + 0B02D893464CD1AA4EC9495A6C0FBAB6 /* FIRStorageTask.h */, + C9833FD8B66A1AA07AFF0687BAA33286 /* FIRStorageTask.m */, + D2DEB829F75D19F6A96A02CE8E216FA1 /* FIRStorageTask_Private.h */, + 38B690DCEA9427D80930EAB58024467C /* FIRStorageTaskSnapshot.h */, + B54C585EF7038D6E900107B27C41362B /* FIRStorageTaskSnapshot.m */, + 5BDDE1C8BDEA616246AD25A843C83C0B /* FIRStorageTaskSnapshot_Private.h */, + 67A202C7FB39D4EF6220EB50BAA61AFE /* FIRStorageTokenAuthorizer.h */, + F036049EC79DBAF2E473B1A9F7BF8D11 /* FIRStorageTokenAuthorizer.m */, + 764B12FF08FBAAAC81693F5927AEABED /* FIRStorageUpdateMetadataTask.h */, + A29139C652B1A548F84E6EFC698953C4 /* FIRStorageUpdateMetadataTask.m */, + EC03F375BA39952863BFCD4DE1C9BCD3 /* FIRStorageUploadTask.h */, + 85963F5A5D4793A9C69D9C6A48407761 /* FIRStorageUploadTask.m */, + 1564C41BABD3DE7AA9CA05FEC60DFFD6 /* FIRStorageUploadTask_Private.h */, + 35CAD52DBF73AB5BE8FA7BD10435643E /* FIRStorageUtils.h */, + EB72BA1B95C57CA801DFED265DFC13D2 /* FIRStorageUtils.m */, + FC629AA5A207E934847DA56D53E02668 /* Support Files */, + ); + name = FirebaseStorage; + path = FirebaseStorage; + sourceTree = ""; + }; + 2B99F95D61A1D7CBB42D5B1C57DD53D2 /* Reachability */ = { + isa = PBXGroup; + children = ( + 4BA61BB6DA2B3B8637F8722F9AA18F5F /* GULReachabilityChecker.h */, + 8AD08C35B5ACC18737C7E17D782539A9 /* GULReachabilityChecker.m */, + ECA1431D8C20F0D81062BFD28CB77A98 /* GULReachabilityChecker+Internal.h */, + 24A357EADAA35A7EF0EA56AA88103251 /* GULReachabilityMessageCode.h */, + ); + name = Reachability; + sourceTree = ""; + }; + 2C7236482012FD427A5DF1CBB6F225EC /* PromisesObjC */ = { + isa = PBXGroup; + children = ( + 10CEE0353BF9A5552A076306DA76AEE7 /* FBLPromise.h */, + A069F158CEFBA4E38C45563122AFCC5F /* FBLPromise.m */, + 2D2DDAE0A59EACE0F9CF5B3655B713FB /* FBLPromise+All.h */, + 69279375BEBF6427D31ED9DC4A523D78 /* FBLPromise+All.m */, + CED22AA9ED7E6EE034D56F18A5F55FC0 /* FBLPromise+Always.h */, + BCB47C109880284CCAC55AF2BD005BFB /* FBLPromise+Always.m */, + C499E907E739C12D9058162F8970BAEF /* FBLPromise+Any.h */, + 5404F30E0CBEEC5274DCB96F2A740A85 /* FBLPromise+Any.m */, + C4A53C14BCDA2F6609BF3286C408518F /* FBLPromise+Async.h */, + 46A8D09E3ABE20DB3AF5BCBC70C770B6 /* FBLPromise+Async.m */, + 65B219104CD42208B88312DE148CB3A0 /* FBLPromise+Await.h */, + F451879A1A9A3D5704CEC1CA6EF6F24B /* FBLPromise+Await.m */, + E62BA6BBCD5F0BB2FCD80BEF9750D13D /* FBLPromise+Catch.h */, + 10E687CA6920D53CFA44E0E9B9ED3E2A /* FBLPromise+Catch.m */, + 3CAEE40E2A06A4534FC90D028269EEAE /* FBLPromise+Delay.h */, + 573C2D9A17826A7450441A7FBCCD3014 /* FBLPromise+Delay.m */, + 4E5F43CF7B994C577E41DD7E44C33231 /* FBLPromise+Do.h */, + C78C74720DE09E30B23A6F9C9B6F5242 /* FBLPromise+Do.m */, + C90626A1C745B85C9BAF1B2F0D9A7B81 /* FBLPromise+Race.h */, + 4CEB318E95935B837B5592E7BE729383 /* FBLPromise+Race.m */, + 169EC26D74379B8E784D2BAD7F05FBAA /* FBLPromise+Recover.h */, + A67AFCD9FDFD86A36567F4CA75A18EDD /* FBLPromise+Recover.m */, + DE3965AFA52554A33633B6C0264AAFB7 /* FBLPromise+Reduce.h */, + 6FA2962149836A8999CDF110AAD149CC /* FBLPromise+Reduce.m */, + EDC8107A0FA008F847D143F5095FCA46 /* FBLPromise+Retry.h */, + E0621BC05ED00710FFB1A6F7DA1AE42A /* FBLPromise+Retry.m */, + 818E56D83F281D68C11461EBA7312C1E /* FBLPromise+Testing.h */, + 62FF2415F7CE0F63E2A28F7B9E7F203F /* FBLPromise+Testing.m */, + 925C41F8B9D85ABE6F2C5D11D6784234 /* FBLPromise+Then.h */, + 61AB353792B56B5B30FA24FA07336722 /* FBLPromise+Then.m */, + 50BD34FADDD845EBC8222D9EB3995F05 /* FBLPromise+Timeout.h */, + E4F2A464610BC0BCA8327F2EFD71673D /* FBLPromise+Timeout.m */, + 9EA4E84EC07EDEE7CEB2CF5CB07768D0 /* FBLPromise+Validate.h */, + 349D453606D972CC4125A9235D6AEFEA /* FBLPromise+Validate.m */, + F8B0B924EF0FBA3293977F67BC3ADB6A /* FBLPromise+Wrap.h */, + 1DC7679A2F6487DA883CD86CD58DD9FE /* FBLPromise+Wrap.m */, + 1C7959E841ED9CAC4E3DFABCC07D4C93 /* FBLPromiseError.h */, + 4D7BA2171283849317F64AD374A314EA /* FBLPromiseError.m */, + 823FF738D2EDB86AD387E9C9A0628A1F /* FBLPromisePrivate.h */, + 4900DB7C20F8911744B754D0004709A8 /* FBLPromises.h */, + 411088EA2437C8F76046AC0A1E101059 /* Support Files */, + ); + name = PromisesObjC; + path = PromisesObjC; + sourceTree = ""; + }; + 3A97A70077F1F646976B16CF07F2DDB4 /* GoogleUtilities */ = { + isa = PBXGroup; + children = ( + 6BC74E78EDF240E1ECBFB5A2680D374B /* AppDelegateSwizzler */, + 28A550D67DF0EA2F2C0578DDF7F7AA0F /* Environment */, + 3F9ED7C6C218AA0EBD024D508049B2A1 /* Logger */, + 623653C29F356AFBF1E115F5A12EDBBF /* MethodSwizzler */, + 74998DE556BACD47E2FBFD34C7B650FC /* Network */, + 6DAE183E963B6405257BF08259213396 /* NSData+zlib */, + 2B99F95D61A1D7CBB42D5B1C57DD53D2 /* Reachability */, + 3C04A26FCAE9FAA43EE0A6026EF2CEEA /* Support Files */, + 9A1D937713BDB35616D1ABCBB5BA4A65 /* UserDefaults */, + ); + name = GoogleUtilities; + path = GoogleUtilities; + sourceTree = ""; + }; + 3C04A26FCAE9FAA43EE0A6026EF2CEEA /* Support Files */ = { + isa = PBXGroup; + children = ( + AFD9F1C347A7E1767AB75D4D6310C2FC /* GoogleUtilities.modulemap */, + 7B05C4EB3F8989AA897BCBBBC215D6AA /* GoogleUtilities-dummy.m */, + 4292BBBC71583AC274A17B5EA2DEA043 /* GoogleUtilities-Info.plist */, + 9AD952A817926DC83697902428396A10 /* GoogleUtilities-prefix.pch */, + D678FD741DD09088553BA3DC1E003846 /* GoogleUtilities-umbrella.h */, + D203DE15B02674646A391ECDC4236920 /* GoogleUtilities.debug.xcconfig */, + 15F815C512EA7B4CD9D9AB719AABC2DF /* GoogleUtilities.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleUtilities"; + sourceTree = ""; + }; + 3F9ED7C6C218AA0EBD024D508049B2A1 /* Logger */ = { + isa = PBXGroup; + children = ( + C932FA22B4630537177123F6782EFBC2 /* GULLogger.h */, + 11C637F7FD1011CD32D6B2CF1B22A474 /* GULLogger.m */, + 33E64FB96AE1E5878000B5A0DF0ED00C /* GULLoggerLevel.h */, + ); + name = Logger; + sourceTree = ""; + }; + 3FDC7886E20278CBF745C468C159B128 /* Support Files */ = { + isa = PBXGroup; + children = ( + 809049EFAF08B2C4551CFB733542CEA5 /* FirebaseCoreDiagnostics.modulemap */, + 7F5524306327B8BA3131DB42B97A17CD /* FirebaseCoreDiagnostics-dummy.m */, + 342865614E6D95B35DC5F1180BF36A4B /* FirebaseCoreDiagnostics-Info.plist */, + 58B98A3CF9D1D67D9B4602B856D83CE1 /* FirebaseCoreDiagnostics-umbrella.h */, + 0C0B61C5273C700F880D6781D3AF1920 /* FirebaseCoreDiagnostics.debug.xcconfig */, + 16A005FC0FE4E4802BA3D80F616EDBE2 /* FirebaseCoreDiagnostics.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCoreDiagnostics"; + sourceTree = ""; + }; + 411088EA2437C8F76046AC0A1E101059 /* Support Files */ = { + isa = PBXGroup; + children = ( + 673E745E6EDF1CEA84454171E55EDA98 /* PromisesObjC.modulemap */, + 25E645CD0A247B7C65BC6B8E58799DDC /* PromisesObjC-dummy.m */, + 75C5467758DF25A71712616698EFBF6C /* PromisesObjC-Info.plist */, + 27C158781A825E2584EA79FBE472E11B /* PromisesObjC-umbrella.h */, + 00E9ACE5B742B168BBAD473E28C5130C /* PromisesObjC.debug.xcconfig */, + D508A6DD4E5CBF53FD46E6F4ACBE445F /* PromisesObjC.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/PromisesObjC"; + sourceTree = ""; + }; + 4FFEC88D8C8E418DA583D7ECDA0EDC74 /* GTMAppAuth */ = { + isa = PBXGroup; + children = ( + 6BDEEB8A7411C302E9837483C2298F14 /* GTMAppAuth.h */, + 2FAB6110EBCEF5EFD9AAF97FB1E323CD /* GTMAppAuthFetcherAuthorization.h */, + 2B8DBE56121715EE74A27E96DF805741 /* GTMAppAuthFetcherAuthorization.m */, + 6350872202105F88AB9E4C49B955A981 /* GTMAppAuthFetcherAuthorization+Keychain.h */, + 34EE00313A78D550D8644DDF8C527845 /* GTMAppAuthFetcherAuthorization+Keychain.m */, + 810D84765A63AC3EFC5E3C943E7597E3 /* GTMKeychain.h */, + E36DB6E3227A68055C28F6B1FC291F50 /* GTMKeychain_iOS.m */, + 62B5C69DF77E1FC8B2CC1480BB7776A2 /* GTMOAuth2KeychainCompatibility.h */, + 1298FE36D6175255C29C7661A7C10629 /* GTMOAuth2KeychainCompatibility.m */, + F5FA5811622F93C00EC912C309CB7455 /* Support Files */, + ); + name = GTMAppAuth; + path = GTMAppAuth; + sourceTree = ""; + }; + 53D1D5B885D8DB77D31ACD2A834BBE51 /* Core */ = { + isa = PBXGroup; + children = ( + 6C8F2633D88D1F74962838B253D72FCE /* AppAuthCore.h */, + E61FAA8E21834BFFB167837F4917911E /* OIDAuthorizationRequest.h */, + 0BA57690C4CA9DFE949ED25284DEB517 /* OIDAuthorizationRequest.m */, + 762FA9EE5DB6C426EB4469042AC1AF92 /* OIDAuthorizationResponse.h */, + 008F4820544BC65FA5681C6A4E10A41A /* OIDAuthorizationResponse.m */, + 376756AE54DA1CDF00DF5DE0090FE3FF /* OIDAuthorizationService.h */, + BDE67C480BC4E7C0C8D3379267B21193 /* OIDAuthorizationService.m */, + CA3DE504B14BEEF56B3ABB1C443B66D5 /* OIDAuthState.h */, + 0992AED4D85D10AED6036ECFCAAF7207 /* OIDAuthState.m */, + 052053BBDBFA807842AEFBCF43F360FB /* OIDAuthStateChangeDelegate.h */, + 57D4AF8B6EB8F9379CB8F2631DF57FF2 /* OIDAuthStateErrorDelegate.h */, + B89C71BCD83F5C915E0B7B88E0783F5A /* OIDClientMetadataParameters.h */, + 01A4C1808C82E6CD358A94DB8090721E /* OIDClientMetadataParameters.m */, + 48FF0BF87B15F6A87546A37B2BE1679A /* OIDDefines.h */, + 1D873F482DABA5FEA5DF77519B4A35C6 /* OIDEndSessionRequest.h */, + EE75160016ACEC2C076DE682CBFC27D7 /* OIDEndSessionRequest.m */, + F31F9DA1BF7C971697A98B2825B32A75 /* OIDEndSessionResponse.h */, + C75B68AA4C55046DD41596EEF217E773 /* OIDEndSessionResponse.m */, + 155468BB75CD9DCF1B69D9F7A0A9355D /* OIDError.h */, + 06E17AEBC3D9DCBAAA1DF718952385F8 /* OIDError.m */, + 75E656E2ACA0B8C607F571F7D16128A5 /* OIDErrorUtilities.h */, + 6EF13F13E0C7FAD491A17E36510E58B5 /* OIDErrorUtilities.m */, + CDC596C717FC35E61C792FFD5B68DCDE /* OIDExternalUserAgent.h */, + B5F0E87509D9331164A5F4D765B1A3D0 /* OIDExternalUserAgentRequest.h */, + 924E549ABA7E7BBBCFAC5E46CA17885C /* OIDExternalUserAgentSession.h */, + 3EB529903C3343CDA096444732E78D38 /* OIDFieldMapping.h */, + 585ED8010AE1A4B72569E70262072162 /* OIDFieldMapping.m */, + 261D24E6A7E8FE448A9D6BBDBEAE06D4 /* OIDGrantTypes.h */, + D2E9C90D84A48DE2D192DE4878590DC3 /* OIDGrantTypes.m */, + 57654CEC144ACD0FFCABF85243288B86 /* OIDIDToken.h */, + 0FA4EB3669CA064C1FDF3FDF3E4098E6 /* OIDIDToken.m */, + 16AF194D65A9EDA527517C4CBA700597 /* OIDRegistrationRequest.h */, + CEADACE08A5687E217E73FEB4D216E2D /* OIDRegistrationRequest.m */, + CE9B81EED1EAD62E147C5B7DE06E7DE9 /* OIDRegistrationResponse.h */, + AF28C7AA75034B0E472FCB46591FE86D /* OIDRegistrationResponse.m */, + 156E36CC1801474606A0B980E1DF1182 /* OIDResponseTypes.h */, + 8BB9C5BE4514F02342045406DF9624D8 /* OIDResponseTypes.m */, + 4FBD09FC244F8C77BA89C81EB61375D1 /* OIDScopes.h */, + A63980E1EAF8FC62A63C8A59A8AB6541 /* OIDScopes.m */, + 77CA828E70063B77546CDEF7F69497FF /* OIDScopeUtilities.h */, + 6189375E4157BB1E09D2728778079CC1 /* OIDScopeUtilities.m */, + D0347ABD7E493B8A79752245481CB399 /* OIDServiceConfiguration.h */, + F6C0E7581284480F32192794A5A25698 /* OIDServiceConfiguration.m */, + 8FB936E76A9A8C28FD4C57098BA48A88 /* OIDServiceDiscovery.h */, + 56BFB5377F78090CCC71859F9C435F83 /* OIDServiceDiscovery.m */, + 9DF71716C207DAB7D4A96B5EC78F76FE /* OIDTokenRequest.h */, + E3A8051121F638EC5568C79DAC199BA5 /* OIDTokenRequest.m */, + 6EE5385D046245271A0934FA76C066DF /* OIDTokenResponse.h */, + 68C12C2F05F8845F2117F2E65E74EFDF /* OIDTokenResponse.m */, + 8C387865C9997476DD5F58576360815E /* OIDTokenUtilities.h */, + 99974DDC351C326D0E6D04F23686DD5A /* OIDTokenUtilities.m */, + 42488D1FE841F575C61D519426D4364C /* OIDURLQueryComponent.h */, + EA086442AADF2F97230F5EE4868D00A3 /* OIDURLQueryComponent.m */, + 4AF11B4252EB3995828F722EF9E7BB66 /* OIDURLSessionProvider.h */, + DD0492AB09814CBF428CF9310A7DF7BD /* OIDURLSessionProvider.m */, + ); + name = Core; + sourceTree = ""; + }; + 581F5860A8A785C1848BFB367ADBD83E /* FirebaseAuth */ = { + isa = PBXGroup; + children = ( + 65E2B99D595DB983880E6E49B6065571 /* FIRActionCodeSettings.h */, + 00FF6D3534EC1D8A91F5F95AD021827C /* FIRActionCodeSettings.m */, + 4006509B9A0C604BC5178AD2B58C0FCD /* FIRAdditionalUserInfo.h */, + 900D7AA1AF5F2CCCFEC7B2A6D7F92D3B /* FIRAdditionalUserInfo.m */, + 44D2EDB1270B1F582810B370AB8F2F1A /* FIRAdditionalUserInfo_Internal.h */, + 73DDA3AD22CD6A161783A626C136DA24 /* FIRAppInternal.h */, + 9263934336E5BCC5C8C49D503E09B471 /* FIRAuth.h */, + 1A65101F6630AA9877B2525A96442662 /* FIRAuth.m */, + 8E3007F6BD5E438E138650DDACCAA423 /* FIRAuth_Internal.h */, + 2ABB4EE4E5ED740CFBB582C2BB9B50DE /* FIRAuthAPNSToken.h */, + F909B1A1A39DA32987EB786BA0FF883E /* FIRAuthAPNSToken.m */, + C5B786A2F794E5BFB62AFC684ED5B115 /* FIRAuthAPNSTokenManager.h */, + C22B8910D6EF1F33FCF463C140B9FAF9 /* FIRAuthAPNSTokenManager.m */, + 64548224BB9A1948AEC7FB891E88BB5D /* FIRAuthAPNSTokenType.h */, + F8FA12F53A842731E91E4E2D261613DD /* FIRAuthAppCredential.h */, + AF35B0BD464B5D45C6B66A9A600F74F5 /* FIRAuthAppCredential.m */, + 1FDCB2F5383C1A7C7A91F0F135CAC071 /* FIRAuthAppCredentialManager.h */, + 9D469034D09270D26A090BD73BAF7BBB /* FIRAuthAppCredentialManager.m */, + FA08C3D52F16A1EC004CAC114EAB689F /* FIRAuthBackend.h */, + 473112A3CDA01CDBEC8924CAD7682B96 /* FIRAuthBackend.m */, + CB61E9165D81B890E80D2A1EA5182F06 /* FIRAuthBackend+MultiFactor.h */, + 6015A44958D8FCFD5AC5DD46D28EA3CB /* FIRAuthBackend+MultiFactor.m */, + 5A3DAD5C415A8443A0DA97DCE4BB1C5D /* FIRAuthCredential.h */, + F0E73FA2D08DB50ACE6FA0819B438E5D /* FIRAuthCredential.m */, + A9C4A684387AAD595A79267AB8478CC2 /* FIRAuthCredential_Internal.h */, + CEA28D4D4EDF2349738CB345D7EAA2FB /* FIRAuthDataResult.h */, + 6148070EDD3BDC2C008E97051E5E51CB /* FIRAuthDataResult.m */, + 6068E3E88D5B4912A996A1E395BEB211 /* FIRAuthDataResult_Internal.h */, + 3002482FBBE4FC29A381308810AAFA04 /* FIRAuthDefaultUIDelegate.h */, + 334EAB92C832A8B1A25E76ED920D2F60 /* FIRAuthDefaultUIDelegate.m */, + D11EE5273DF1F4D4E3FDEE12058DFDAC /* FIRAuthDispatcher.h */, + DE23FFEDE913A0F515A9DD8F1CF6D5DE /* FIRAuthDispatcher.m */, + 7F0A65267EACC1715344BFD364530CF2 /* FIRAuthErrors.h */, + F26BE0CF90BD08FB506A58DF1E66DFAC /* FIRAuthErrorUtils.h */, + AECF8D6DA7C8A464989CB066D473F472 /* FIRAuthErrorUtils.m */, + 7705D67F509F485AE9F635CEFF68D4FC /* FIRAuthExceptionUtils.h */, + 30554C35CED21FD072A6C0539122D9CD /* FIRAuthExceptionUtils.m */, + 55E877FAB1A07AA39659E1E33B454A34 /* FIRAuthGlobalWorkQueue.h */, + 2D2A0CFFCC140A4E6C194F8D0FC5D628 /* FIRAuthGlobalWorkQueue.m */, + C6959E1A1109365FD844CBC9D553F283 /* FIRAuthInternalErrors.h */, + 4C83DEDF6D65FAC677439496F70A8003 /* FIRAuthInterop.h */, + 9003091EE6B741989C260584A1A67492 /* FIRAuthKeychainServices.h */, + 993295ECC4A249DC7D75827B7832BFAF /* FIRAuthKeychainServices.m */, + 7EE4774B8121D656C797F2900CD8BDBE /* FIRAuthNotificationManager.h */, + D2416E1A611AAAA6CE13CE9FB3A88784 /* FIRAuthNotificationManager.m */, + 5E741077ED9CDA63CB0EE1E4387BB7B8 /* FIRAuthOperationType.h */, + BA00DAB93EF0A75C56ED6785FACD5EF3 /* FIRAuthProto.h */, + 29D5A4375D1E8A2A55723BFF02AA7005 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.h */, + 7235427A1267E29C913763C2DD9508AF /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.m */, + 562417974B48784FF00BE78597B8C019 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.h */, + 156A0CE6C28B38095AF9138DBEE5A713 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.m */, + 75FAA3E93E73C340192C7B4B9471389B /* FIRAuthProtoMFAEnrollment.h */, + CC289465F3C72999640A1007EB3AB692 /* FIRAuthProtoMFAEnrollment.m */, + 49A0147206768735137648B732ADD53C /* FIRAuthProtoStartMFAPhoneRequestInfo.h */, + A0ACEEDB9C66A05F00FB2DC2683FD087 /* FIRAuthProtoStartMFAPhoneRequestInfo.m */, + E8697049410C51707EB215F2B6E1EEF7 /* FIRAuthProtoStartMFAPhoneResponseInfo.h */, + 65CB8A235F0A6036357C260E72FF4F51 /* FIRAuthProtoStartMFAPhoneResponseInfo.m */, + ACB7AE213B5C354BC61016F4F3AA5E23 /* FIRAuthProvider.m */, + 695E99910948F9E8E6793FC52BD6AA01 /* FIRAuthRequestConfiguration.h */, + 331717291051CAD5BB3353BB8C494A50 /* FIRAuthRequestConfiguration.m */, + 0AA3BC8FBC301E1AD271B8BC56131017 /* FIRAuthRPCRequest.h */, + FF8F5D3FDDBE05A714D93F601CAFB9A6 /* FIRAuthRPCResponse.h */, + 9D3C88BA14651AAF531A1534E6274A7D /* FIRAuthSerialTaskQueue.h */, + 1F0FD4060063C5168EA8438027D27297 /* FIRAuthSerialTaskQueue.m */, + A71C4B5D790AC1036C87931CE820B177 /* FIRAuthSettings.h */, + 2A5EFA30C44EF4FB68F3C3D45A179EC3 /* FIRAuthSettings.m */, + B0FA2F0A3D5C566608F18B383B6CF044 /* FIRAuthStoredUserManager.h */, + DD3AD31088110FDA73241B3581A2B2D7 /* FIRAuthStoredUserManager.m */, + 48BCA366BED224540BBF9225961D5874 /* FIRAuthTokenResult.h */, + D2A7778C875EA74A7A8967EDFCD4A25B /* FIRAuthTokenResult.m */, + 147ABC58AAD1BAF83AAFFD3ED20DF9CB /* FIRAuthTokenResult_Internal.h */, + BF1EF2B382CEE39048BFA8A04FA59482 /* FIRAuthUIDelegate.h */, + D9E223315FB9AADC49B259DD2B5AF5BF /* FIRAuthURLPresenter.h */, + 7D89B61F748E61F84C2D14454827CD41 /* FIRAuthURLPresenter.m */, + 6FB877E48D135890070C81A252F9515C /* FIRAuthUserDefaults.h */, + 3A0BE22AF48CFFC11F35F50CA46D4256 /* FIRAuthUserDefaults.m */, + 37F19532C1B98CB916ADC4049AD0646E /* FIRAuthWebUtils.h */, + 477FFB4052347BAD985B3A94763834BC /* FIRAuthWebUtils.m */, + 08441C78A0B36E7813F97FB64E0E9B1F /* FIRAuthWebView.h */, + 25BF8489D43A221CCEECB7FB5BAB2A7B /* FIRAuthWebView.m */, + 6664F046DE36C873274CEE8DFF2BECFD /* FIRAuthWebViewController.h */, + 21E390ED7946A6255192CC662B974485 /* FIRAuthWebViewController.m */, + EB2E6210777537A1E815E5BB3432D4CF /* FIRComponent.h */, + E8912EB183AA4629889505B7BB5CAB6F /* FIRComponentContainer.h */, + A58F87C6180D374437CE7E706591B563 /* FIRComponentType.h */, + AA9B4B8BCB07AC966A24D358AE74A0E6 /* FIRCoreDiagnosticsConnector.h */, + F98BAF8C84B54154210F7ACBE4D637A0 /* FIRCreateAuthURIRequest.h */, + 7BCE6DCCBAC25268B5B31598C195FF5C /* FIRCreateAuthURIRequest.m */, + DC72213D4B3FE7DE0AE14E86B63763C3 /* FIRCreateAuthURIResponse.h */, + 609ABC8D27C7BECC6DE50BB8016F27BF /* FIRCreateAuthURIResponse.m */, + D9E2521795EDDB2463612C8580708673 /* FIRDeleteAccountRequest.h */, + 757AFA09EEDF7E69BA225B0049AE4C79 /* FIRDeleteAccountRequest.m */, + 0BEBBED032A65D6D7E7177E7EBD6307E /* FIRDeleteAccountResponse.h */, + F9C18C1536C6548F5BB3AE6687B9A6CA /* FIRDeleteAccountResponse.m */, + D85A7B28B871DD677E7668E92BB6D96A /* FIRDependency.h */, + AAF1F950FB05508CDC5E0BADE1A27F22 /* FirebaseAuth.h */, + 31403F1670FC70281DB296638EBBA5C0 /* FirebaseAuthVersion.h */, + 218CAE055A0262CE3E2519316FDB660B /* FirebaseAuthVersion.m */, + 69F44E5B36FA5106930486C4FA63C17B /* FirebaseCoreInternal.h */, + FFE5D5FAFCA8CD85996CACEF15BA5467 /* FIREmailAuthProvider.h */, + 775B864B453C9AE0D8B96507F09A9F80 /* FIREmailAuthProvider.m */, + B005A07BEF4B4650B74F86B0F91D2E75 /* FIREmailLinkSignInRequest.h */, + 843D31A14C08E44DE861EC9068CF935A /* FIREmailLinkSignInRequest.m */, + 24A6A8B562A7BB27357C8B086C0E3880 /* FIREmailLinkSignInResponse.h */, + E94E0DEED20A943669F5DC4D7EE30AB7 /* FIREmailLinkSignInResponse.m */, + 31FEC4E1D3426CA59F02F81AF0A49EC6 /* FIREmailPasswordAuthCredential.h */, + C56E3C6C0454607B87EA00A5D33CAB73 /* FIREmailPasswordAuthCredential.m */, + 86785462374CEE6C2A26DF27723AFD08 /* FIRErrorCode.h */, + 331D5AAD7CCB53498DF832B15B48EB0B /* FIRErrors.h */, + 0C06F2CB64F40C1BEFC844D191BCED3C /* FIRFacebookAuthCredential.h */, + 369A1A5944F95579358CD6744CA18E2F /* FIRFacebookAuthCredential.m */, + EC9477E5C763D86BC2707DDA3A103547 /* FIRFacebookAuthProvider.h */, + BAAEF18BC7684AEDE7B7A4B4E04FB187 /* FIRFacebookAuthProvider.m */, + F8733E756435BEDCF24F263A778E0ECC /* FIRFederatedAuthProvider.h */, + D613FF318A802CAA63501906CD9204BC /* FIRFinalizeMFAEnrollmentRequest.h */, + 279B1FA79AC353861C5CF0F52B5147CA /* FIRFinalizeMFAEnrollmentRequest.m */, + DF0342C0DE83E41409C0FC91022A091B /* FIRFinalizeMFAEnrollmentResponse.h */, + 77AC5C0D1A2EAB140E1050E088AAC8AA /* FIRFinalizeMFAEnrollmentResponse.m */, + 6F6CB189D81B7A5D42DB2B7674676C63 /* FIRFinalizeMFASignInRequest.h */, + A29EA43E4DC3B153192A8339CC174C3E /* FIRFinalizeMFASignInRequest.m */, + 3F990D243683DB1B69B7DD45FE31E6E7 /* FIRFinalizeMFASignInResponse.h */, + 2C08645CF610E0A55FA7C8135E3E4B04 /* FIRFinalizeMFASignInResponse.m */, + 8C9DAD4624BF9ACE5C50723DE347FA8F /* FIRGameCenterAuthCredential.h */, + B790DE03DD206859035C01A0ECA835C7 /* FIRGameCenterAuthCredential.m */, + FD8A4AC55991A3986691EF3AC1B9D012 /* FIRGameCenterAuthProvider.h */, + 70C7B1A3C16EB7A855387B627E028E99 /* FIRGameCenterAuthProvider.m */, + 8BFD29E8171D39915525EB07724F0AEB /* FIRGetAccountInfoRequest.h */, + F06F4E8D581CDEEFFC49BC1FC11DA980 /* FIRGetAccountInfoRequest.m */, + E127A35AD926485DF36164AB3C03700D /* FIRGetAccountInfoResponse.h */, + C76496A8B14E858B7350925B0A20A7DA /* FIRGetAccountInfoResponse.m */, + B7698798113828A6F12BD9B8EC907A4B /* FIRGetOOBConfirmationCodeRequest.h */, + 15EDF646C56C65236F9F00B1FAF8A64D /* FIRGetOOBConfirmationCodeRequest.m */, + 67F83985ACA93737DD4D45DB6C0CA19B /* FIRGetOOBConfirmationCodeResponse.h */, + 65EE3073A02E48ADF059D298867A4902 /* FIRGetOOBConfirmationCodeResponse.m */, + 74FF9CA663893AB6239A094AAAAEA2C8 /* FIRGetProjectConfigRequest.h */, + 371A2FCFDB806C4E3FDC7EDD27A1603D /* FIRGetProjectConfigRequest.m */, + F1A95286B9447DB591D70DF43B8B09E6 /* FIRGetProjectConfigResponse.h */, + FC0EA04586CCBCCD2808FC6B7762C4C0 /* FIRGetProjectConfigResponse.m */, + 0FCE96FB03C7E2B07F0D846224B8050B /* FIRGitHubAuthCredential.h */, + E224F372FAC278DFD97371C8ADC9E6E8 /* FIRGitHubAuthCredential.m */, + 0CBCAC752D4D966314C7ED6C79EF83E9 /* FIRGitHubAuthProvider.h */, + DAF9DED7488ECE428D645CC657AD96A7 /* FIRGitHubAuthProvider.m */, + 6E92ABD50E475C05DDFA7B0A5531B74A /* FIRGoogleAuthCredential.h */, + CB2D63A74DA934A6BEF857D02B49169F /* FIRGoogleAuthCredential.m */, + A99400EE0057F9ADD1A81323F1926953 /* FIRGoogleAuthProvider.h */, + 7C6EF5A4DB9F566411010DC8177A31C8 /* FIRGoogleAuthProvider.m */, + 9C95D1C7C8FCD7CAF183BC0E158F01C7 /* FIRHeartbeatInfo.h */, + A554AF875831B385C25328CECE189540 /* FIRIdentityToolkitRequest.h */, + B0C412BBE0A796A1761E0B94E8A1A4C2 /* FIRIdentityToolkitRequest.m */, + 180C6EA8C3894CB86B604C1AAA40521F /* FIRLibrary.h */, + B8FC9290AD16001E5097C8CDEDCEB32E /* FIRLogger.h */, + 8EE688B7F2552F591256057AE7161815 /* FIRMultiFactor.h */, + 846FC1E466FBFE0D850CD2366D07FD41 /* FIRMultiFactor.m */, + DE8F826E478831E2D720397A11BCC6EA /* FIRMultiFactor+Internal.h */, + 1F2114000F4B4E452E61D687C2422EB2 /* FIRMultiFactorAssertion.h */, + 67159BAA40CC337613A80836DD8BF37D /* FIRMultiFactorAssertion.m */, + 4322D71552AD5DA1FD0A28B69543F2A1 /* FIRMultiFactorAssertion+Internal.h */, + 2FDF1C00DD35EAEB9F29A29E8E1AEED7 /* FIRMultiFactorConstants.m */, + DB6D2539EA7C1522AC8F8066C70BDAF5 /* FIRMultiFactorInfo.h */, + 95D34077E7127C594A944B755B63D902 /* FIRMultiFactorInfo.m */, + 5BF69E8882B8B2DB954A2A48042B84CF /* FIRMultiFactorInfo+Internal.h */, + 5604269047012A590F82880FF4FB18B8 /* FIRMultiFactorResolver.h */, + 875E1AF5B72E29DF5D842CD418D664AC /* FIRMultiFactorResolver.m */, + 40D807BDAEF7E00EC311084CEB3E716B /* FIRMultiFactorResolver+Internal.h */, + A1199F3B6D178FFC9022E990B57BF88D /* FIRMultiFactorSession.h */, + 78AB14E26E13BE6E71FA466FD1F7C0FC /* FIRMultiFactorSession.m */, + A55165D05F5298D7EC70AC6D256E7480 /* FIRMultiFactorSession+Internal.h */, + 9374F6D4F9703C1046AF6A58B1D1F189 /* FIROAuthCredential.h */, + 91200D0F48E695F4F2B5024B2FAA9F80 /* FIROAuthCredential.m */, + 79C0C49B9FD1D38A300F17C741E09F97 /* FIROAuthCredential_Internal.h */, + 2CC6A8024E61AF153A776058F0093984 /* FIROAuthProvider.h */, + AF4DFD6F05C1DBDF4AB4A397879384A0 /* FIROAuthProvider.m */, + DB941D9DDE37F386275A2A26D65A2292 /* FIROptionsInternal.h */, + 9B18A4515BDC97476AC776D94BEC8918 /* FIRPhoneAuthCredential.h */, + E0EA93F03F796711CD33A8D1A75BE58E /* FIRPhoneAuthCredential.m */, + C4D13117E55C177BC67ADD141D7A6557 /* FIRPhoneAuthCredential_Internal.h */, + 979EE14740E14EBC7F7EC39F2D7B7574 /* FIRPhoneAuthProvider.h */, + 5440B26AAF05B19A6349A85F31249BF6 /* FIRPhoneAuthProvider.m */, + B53E593E59C566978EEABD9BBAE4E82C /* FIRPhoneMultiFactorAssertion.h */, + CD1796471948B825202E4B28A5B2A6B9 /* FIRPhoneMultiFactorAssertion.m */, + 494F76FE5143C8D636FE5CAB2CA7372A /* FIRPhoneMultiFactorAssertion+Internal.h */, + C74F354DE76EFF3D897FDE22F1864112 /* FIRPhoneMultiFactorGenerator.h */, + 1D3F00A4E6D8568D60392BAC86AE8673 /* FIRPhoneMultiFactorGenerator.m */, + D8115227BAC33FB3D00E2975EE0BD24C /* FIRPhoneMultiFactorInfo.h */, + B59BE61A40373B7371A718989F31D704 /* FIRPhoneMultiFactorInfo.m */, + FC0FDCC1AA88D683B0D4E35474D6DE84 /* FIRPhoneMultiFactorInfo+Internal.h */, + FA0BE7E74ED2EBA52D88C5CDED4BAA14 /* FIRResetPasswordRequest.h */, + A7842D8719CBBA97D03A9F7A3133A20B /* FIRResetPasswordRequest.m */, + CE21C56EF37A104800F9B6C5FFFFA0DD /* FIRResetPasswordResponse.h */, + E3B94329AF814460FDA387EC4AF66927 /* FIRResetPasswordResponse.m */, + 84B17AAF40781DB944D8E2218CE3D551 /* FIRSecureTokenRequest.h */, + 0BEF95068A2B04D39985E4D2821BDE9E /* FIRSecureTokenRequest.m */, + E9D51A261F16AF25D0F6D395165163D6 /* FIRSecureTokenResponse.h */, + 9116AE55C96DD4B7CC8A610D2763F4CC /* FIRSecureTokenResponse.m */, + DD0D0E3CC089D8D56B6F1EA76C078E22 /* FIRSecureTokenService.h */, + 31C485AEEEEE2964C83DDD0480C6592E /* FIRSecureTokenService.m */, + 972070C5155A5F1E91B6A9DB11D2258B /* FIRSendVerificationCodeRequest.h */, + C2A84F61584DBCC3BD946DCDB89CB968 /* FIRSendVerificationCodeRequest.m */, + FC0ADC33764603966493C028E141A96C /* FIRSendVerificationCodeResponse.h */, + 55D4FCD5BAA0A7583F30CF79D5F369A7 /* FIRSendVerificationCodeResponse.m */, + 477A700BD923CF5A1643043ADC94EC97 /* FIRSetAccountInfoRequest.h */, + 605F66FBD87C009EECDEEFB5EFD3BACD /* FIRSetAccountInfoRequest.m */, + 9C199C6C880F5BBB8AC4A31DBDFD42AE /* FIRSetAccountInfoResponse.h */, + BB397D64A004B2E58E996CA6126F9E5D /* FIRSetAccountInfoResponse.m */, + CEC1393DC856702660ACD7A0599DBD56 /* FIRSignInWithGameCenterRequest.h */, + 3D06E70882D19FEFCE28914350700F23 /* FIRSignInWithGameCenterRequest.m */, + BE847A5DCB4BFC93207699CCE355AD02 /* FIRSignInWithGameCenterResponse.h */, + 8075BDC5128A59A8A356556917442DC7 /* FIRSignInWithGameCenterResponse.m */, + 187E5952DB3FBDBC83676A1C55427733 /* FIRSignUpNewUserRequest.h */, + AC71EF56D169FAEC6FA1922E3EDE88B0 /* FIRSignUpNewUserRequest.m */, + 9532DBD2E25AE8B4F16B588047B3C540 /* FIRSignUpNewUserResponse.h */, + 00AC724E951A64118AD7189A15610DE6 /* FIRSignUpNewUserResponse.m */, + 7ED5B5B260DA1124ED4F9279DD4FCC12 /* FIRStartMFAEnrollmentRequest.h */, + FB35D2B3E2A95345454CCC31127AFA58 /* FIRStartMFAEnrollmentRequest.m */, + 25585B514F999F152B161BDD883EF1FC /* FIRStartMFAEnrollmentResponse.h */, + 20BC6706A3B2DCD001B2917F79F8F31F /* FIRStartMFAEnrollmentResponse.m */, + 97B15D8306560971C11A226391C02BBD /* FIRStartMFASignInRequest.h */, + A6ACC2CFD2255923C22F0FAE78CA8F2D /* FIRStartMFASignInRequest.m */, + 15CBA6967F032A28843A65A901C56F28 /* FIRStartMFASignInResponse.h */, + 4C544C318DE1B07A1D697B0F86F8E333 /* FIRStartMFASignInResponse.m */, + 00DECA92B7EE6396FB998E278B411EB9 /* FIRTwitterAuthCredential.h */, + 0AECB71732ABD8587D9BB4DE4FD97046 /* FIRTwitterAuthCredential.m */, + BEB00CA7F1B74B70E55D98ACA2FEE9E8 /* FIRTwitterAuthProvider.h */, + 12F9164B27690D519BFFCC086D81CFFD /* FIRTwitterAuthProvider.m */, + 76653C0C50EDD5D4C16513CE8BEEC454 /* FIRUser.h */, + AFD9FA2AEB376B05A4B4A9FFA4D1C6A5 /* FIRUser.m */, + C9A38DCEB8119B8F88A776D0122E0642 /* FIRUser_Internal.h */, + 82C7731D87C6760CDF18BCA19341307A /* FIRUserInfo.h */, + 43C43DE3698D5BA2BF456C6F2F7532C7 /* FIRUserInfoImpl.h */, + C8DFE6DAEF4281B9CBB00EC08215796B /* FIRUserInfoImpl.m */, + C25D07BAAE13143BC5F5C71355C0D5B6 /* FIRUserMetadata.h */, + C21C89AC19083B376E164BCC661CB8D9 /* FIRUserMetadata.m */, + A6A6CEC85A5CC5B5C02A3A53996C6DCB /* FIRUserMetadata_Internal.h */, + DDFD93E377D4D37AD058840107B807F3 /* FIRVerifyAssertionRequest.h */, + 9AB447E9106C479163FEB96B7765FE05 /* FIRVerifyAssertionRequest.m */, + 38579428D05E6E50944B74FAE19B1BB7 /* FIRVerifyAssertionResponse.h */, + 667D98F84E5FDD3D4D026D657ABB2756 /* FIRVerifyAssertionResponse.m */, + CE72AB024AB58E38E7CAAC21CEFD758A /* FIRVerifyClientRequest.h */, + 41AB484DC0B19FB371A44E3934FCC0AD /* FIRVerifyClientRequest.m */, + F998DA016600AADC4C4757203652294C /* FIRVerifyClientResponse.h */, + 4E6CE7028A24474F1C666BEEC7568971 /* FIRVerifyClientResponse.m */, + ACB1AD1F6F42BF9BB16AE8500CEB3DA7 /* FIRVerifyCustomTokenRequest.h */, + 3225C5DFD5EEFAA06E0C3E77905A56EB /* FIRVerifyCustomTokenRequest.m */, + 295D5C63FA45919B29F2B47126BA3657 /* FIRVerifyCustomTokenResponse.h */, + 8EEC83A35CA914EF24F3A4863B5C2EA9 /* FIRVerifyCustomTokenResponse.m */, + 509507A836C0211E77888E451937CC3C /* FIRVerifyPasswordRequest.h */, + 0E7D49DB2F3223117BA44B91C6B9E48A /* FIRVerifyPasswordRequest.m */, + 64EC6A649794171EB333535CC75C27F5 /* FIRVerifyPasswordResponse.h */, + CD154F70A82503F71907F09DA04D6A82 /* FIRVerifyPasswordResponse.m */, + 0FB4B2E3214664E3EC1748DB3C76B35B /* FIRVerifyPhoneNumberRequest.h */, + 105D55B1653C85994022CD7D23E05D05 /* FIRVerifyPhoneNumberRequest.m */, + 19DF54507D0D63DE4425E3FE350B9832 /* FIRVerifyPhoneNumberResponse.h */, + C8C4908AAA89E23228B4BAE39DC3B770 /* FIRVerifyPhoneNumberResponse.m */, + A9F703C962F2095B7778365C9317974D /* FIRWithdrawMFARequest.h */, + AC61C5ABD2CCCABB38B49666D763500D /* FIRWithdrawMFARequest.m */, + 9D1C280352A1F5631E02957E16C08DD7 /* FIRWithdrawMFAResponse.h */, + 7853F03B091136CF9515F12807177703 /* FIRWithdrawMFAResponse.m */, + 08E72A8C52BAD62FEB94490A1F2BF9B8 /* NSData+FIRBase64.h */, + 14FE6A4FB9D07E0668CC728919204386 /* NSData+FIRBase64.m */, + 9541EBE607ECC6CB0E9E74DE1E34C2FD /* Support Files */, + ); + name = FirebaseAuth; + path = FirebaseAuth; + sourceTree = ""; + }; + 58857F73CBE4944EC40BAE40C6F729ED /* FirebaseAnalytics */ = { + isa = PBXGroup; + children = ( + F74DFF2EA954084F51F5A0AEAD994BEA /* Frameworks */, + FEF3AB10B6D5592DD5D72BB51EB413FC /* Support Files */, + ); + name = FirebaseAnalytics; + path = FirebaseAnalytics; + sourceTree = ""; + }; + 596C51AED19D744E168FF87149B3DD01 /* GoogleSignIn */ = { + isa = PBXGroup; + children = ( + A614E727274FB818C69C66EC8751DB5E /* Frameworks */, + E6F241A0A1E00B3CC0D32DFEBCDF04A8 /* Resources */, + 04B623AC022CECE0EEA39898BA767119 /* Support Files */, + ); + name = GoogleSignIn; + path = GoogleSignIn; + sourceTree = ""; + }; + 5B199D50257EA2B47977DE95F642803A /* CoreOnly */ = { + isa = PBXGroup; + children = ( + A768CAA71B66068FB09E6EAE5A8B0525 /* Firebase.h */, + ); + name = CoreOnly; + sourceTree = ""; + }; + 623653C29F356AFBF1E115F5A12EDBBF /* MethodSwizzler */ = { + isa = PBXGroup; + children = ( + 580FEBB5E7903DF0A726E950419BFB5D /* GULOriginalIMPConvenienceMacros.h */, + 84DBFD500F6079D0B3DE7D70BF750C3A /* GULSwizzler.h */, + BDEC68EAE51158E1F4BB5115466D6247 /* GULSwizzler.m */, + ); + name = MethodSwizzler; + sourceTree = ""; + }; + 6BC74E78EDF240E1ECBFB5A2680D374B /* AppDelegateSwizzler */ = { + isa = PBXGroup; + children = ( + D1B62426B683A0486229605D8AF442B2 /* GULAppDelegateSwizzler.h */, + 782C0B18B8A79A056DC2C87331FC21DC /* GULAppDelegateSwizzler.m */, + 9EEA4E41181C12F276CA21332BF193E0 /* GULAppDelegateSwizzler_Private.h */, + 78DB579CADEFEB232525FF20715796F3 /* GULApplication.h */, + 4255E63440A44CE02AF3070690D0C948 /* GULLoggerCodes.h */, + 42C7BFFB0E3DE1C0DDD9CA158FDDF6D6 /* GULSceneDelegateSwizzler.h */, + 5F4DC6177BD16CE479E33E760B8781E6 /* GULSceneDelegateSwizzler.m */, + 68C28E759956387D8E25CBB6785BC93F /* GULSceneDelegateSwizzler_Private.h */, + ); + name = AppDelegateSwizzler; + sourceTree = ""; + }; + 6DAE183E963B6405257BF08259213396 /* NSData+zlib */ = { + isa = PBXGroup; + children = ( + 5C403D3BDC74CA4BF92DE5C1E73CF160 /* GULNSData+zlib.h */, + 6D30EF1C0685DD064607D8AC309AB8FE /* GULNSData+zlib.m */, + ); + name = "NSData+zlib"; + sourceTree = ""; + }; + 74998DE556BACD47E2FBFD34C7B650FC /* Network */ = { + isa = PBXGroup; + children = ( + D983B95F647C6BB9155FCAEA8E9C39AF /* GULMutableDictionary.h */, + D3C1B3F5110E2256AB2C545D67205C5F /* GULMutableDictionary.m */, + DB555A10BABB5FF3340F0DA9AA9E7525 /* GULNetwork.h */, + 8C3177C16671C84C8825F706F9F17A4E /* GULNetwork.m */, + E40F8DC8B40272B99AAE3C0E3B49D1B5 /* GULNetworkConstants.h */, + 86FBE6D4358D22E5A6431DB64E093622 /* GULNetworkConstants.m */, + 55ED76CB4443F7E041AB9AC6FA9AAB50 /* GULNetworkLoggerProtocol.h */, + 1F7AF946105D40415BEE2B4C29262A5D /* GULNetworkMessageCode.h */, + 31F0F6B3F5A086DD87C96BDCFA6D3070 /* GULNetworkURLSession.h */, + CEE9C52C8EB244E7F293F1632DCEC5EF /* GULNetworkURLSession.m */, + ); + name = Network; + sourceTree = ""; + }; + 788D72AE3787A270B8003B3F4A11763A /* Resources */ = { + isa = PBXGroup; + children = ( + 7FE12394BAF5BCDF91A1683D1D50C8DC /* ar.lproj */, + 55A5039F460D923DB08EEE1CBDE8081D /* bg.lproj */, + 03F04BE92A78E9CB93B09F492E85AAF1 /* bn.lproj */, + 77AFF048E9D11813E82960D3522E228C /* ca.lproj */, + 45D396EDB48B3E1CED1969E1ABD6A9A1 /* cs.lproj */, + A068D9D7C318C3DEDB62F09C48DF6E09 /* da.lproj */, + C5F00DE74D2EC6196997C150EB6ECE06 /* de.lproj */, + D7BB87477E1647138F76960431BA7280 /* de-AT.lproj */, + 99BF294419A82872B273C32B3313AD54 /* de-CH.lproj */, + FE7B98B1A5BFC14EF81EFCD319A7C848 /* el.lproj */, + 66390B4F65D06861288DF3E89EB760F4 /* en.lproj */, + D532471374ECD1325BAAA8585722C50E /* en-AU.lproj */, + B2C91601666B923A0EC1E3E55055B56F /* en-CA.lproj */, + 5A869C047DA714685FC173B0BEBCEC95 /* en-GB.lproj */, + B0CC498F1F77BEE204AA9B103D245937 /* en-IE.lproj */, + 03239C2D092CAF3AABFEE00AF21A83AA /* en-IN.lproj */, + 9D340BECB137147E09B0C0BDB14FCC42 /* en-SG.lproj */, + 9CED810C143F8723E760A6F7C2DA34C2 /* en-ZA.lproj */, + C454F063088B3509C6ED0D11F3FF4E73 /* es.lproj */, + D6AB56177AAFE39BC48DAAC32ACCF3E3 /* es-419.lproj */, + CEBEF2F06D0AD7AA80B541C2D95934CE /* es-AR.lproj */, + 26FF61F5D948E7FB9711D97EEA148219 /* es-BO.lproj */, + 3F35FE6C627EEBD84D320623CBC3ED59 /* es-CL.lproj */, + 2506B650F36439620CF54F5655EBDEDA /* es-CO.lproj */, + A672DD638BC3C2D318FB66F0D7E6C1F9 /* es-CR.lproj */, + 7C2013D50092AC3FF5988D10C0269AC9 /* es-DO.lproj */, + E9CC25C8A5F883C299D957961F94531D /* es-EC.lproj */, + E04D809D94C88A8E91E01FA4F33D3DD4 /* es-GT.lproj */, + F2036DCCF9E03B57FE8FFCC80F813155 /* es-HN.lproj */, + EF27A4D04F2D6D69190C3B0E898A3BA0 /* es-MX.lproj */, + 58468784E905EC12C0878CEA8C1CA891 /* es-NI.lproj */, + 32286B36029E0A0C5EF3CF7FACFDE828 /* es-PA.lproj */, + F854F0655C7BC1A52D8C680D1EDEF4CA /* es-PE.lproj */, + E54A58182BF6AFB5DC13921079ACA542 /* es-PR.lproj */, + 778802077ADDAF4B7A52B59847FE54DB /* es-PY.lproj */, + 73C7F092D26BAFEA89D9BDF33EA12285 /* es-SV.lproj */, + 0BE0652F32B8FA6E5D02FA260895209B /* es-US.lproj */, + BBE953CA3053CC11FBB998F65D10C853 /* es-UY.lproj */, + 68E6D55D2E5797DAEE6966BAFCF95C5F /* es-VE.lproj */, + 27D4D33D864D9FCB96217A3F5BE9F5D4 /* fa.lproj */, + 3196AD45943E4CD873BAA17255DC4131 /* fi.lproj */, + 044E68ADDD610FF0750545E3E8E7FEBB /* fil.lproj */, + 9F19F2DAB2BE2733FD82D447F48A654C /* fr.lproj */, + 42F6E008885453176BC7D27CA366F6C1 /* fr-CH.lproj */, + 46CA62F34B2D8C856819BEB8C5215DA1 /* FUIAccountSettingsViewController.xib */, + 88D1A747FD5261ACFF61437E691C185B /* FUIAuthPickerViewController.xib */, + 573253504667D85EE768C19D3F939A99 /* FUIAuthTableViewCell.xib */, + E0C87CCE8B50E854B57AD5AA483FAA4A /* FUIInputTableViewCell.xib */, + D46BE344296E1A185ACCE52FC07459CE /* FUIPasswordTableViewCell.xib */, + A7950EBD3C0C73CAF6F2AECCB1F0F04E /* FUIStaticContentTableViewController.xib */, + 1A7A8CD6C8BB3A13F9B114C37E9FEAC4 /* gsw.lproj */, + 20E3C25D260E7FAD721012E746F5ECD9 /* gu.lproj */, + 37C9A4444EFAAC11218633CD24F8D1DB /* he.lproj */, + 331968F42465E8E681660A4F9DE033FF /* hi.lproj */, + 6EA549DC6A9769196F50FEAAFE6F9D2E /* hr.lproj */, + A1045ABFBD7DF90A5E84372D88E5C833 /* hu.lproj */, + 70582D78CBEA51C33A8B82C9FFB723B1 /* ic_account_circle.png */, + 80555E26FEBB765547F06A92F10BBFAC /* ic_account_circle2x.png */, + 85CEC317B81F1610CC32F5A36302B5EB /* ic_account_circle3x.png */, + 310A0ABEA5C28EC185CCC6BE875BBC07 /* ic_visibility.png */, + 0594A0CB5786656C000F34DF38D7548E /* ic_visibility@2x.png */, + D591A8AD1DC179AB95D8C88D42E28597 /* ic_visibility@3x.png */, + 4376CE82EF1BF0ECFA794D85F3766F87 /* ic_visibility_off.png */, + AC0430E28848AB18A3CA8325151A98FD /* ic_visibility_off@2x.png */, + 7CA87D9C42EE5FB93F71C78E42F2D2EF /* ic_visibility_off@3x.png */, + 65B5611A02B54AF167B839A5FB4E668E /* id.lproj */, + B31CEFCCA8222DE30CE0A3C9C1694A1B /* it.lproj */, + 76E51504F5FFB6652AFD71EF86591B2A /* ja.lproj */, + 383473E33BC32486A7A364A9BB0E95C7 /* kn.lproj */, + 904ACA95784DB45F51C8EA34D83966A8 /* ko.lproj */, + 8BE1FBFA703800A2B83E044EE565A1A6 /* ln.lproj */, + 9B5DAA4FAAD2341569C841186C84AB46 /* lt.lproj */, + 1F7DC439F0D2B26FCAA3BB600B86D9A7 /* lv.lproj */, + 4195822B54AB8FA1BEA64F7C1983BAB7 /* mr.lproj */, + 3F1B7DBC84792CBABEBA9ECF5DBBB256 /* ms.lproj */, + 10A31E89F0E82B96B1774125C4430CCF /* nb.lproj */, + F156EBA03AB88203E99DFE8B8BA46A02 /* nl.lproj */, + 2AFED164F46BA096C4E58DA488DF0248 /* nn-NO.lproj */, + 7FAD4119D663241EA3AEADF1D7CE00C5 /* pl.lproj */, + 39D2B86BB6BAD94CA0B74548C99551B5 /* pt.lproj */, + DCE3112310721644BD336BAD8E71CECE /* pt-BR.lproj */, + 90EF156F21BA67E590DD858B42B6D67E /* pt-PT.lproj */, + 64948C59CFBEBBCAC0EE75768B1A66F7 /* ro.lproj */, + F12D465A15972386FC714191DB492F6C /* ru.lproj */, + 01DB54993FD7E077C1A2FDA6680AD562 /* sk.lproj */, + 7F9AF4AD8155223C8FEEE6032B169F66 /* sl.lproj */, + C9865EBDD0EB8C79D569F548638FCC3D /* sr.lproj */, + B07EFDEC4F73E46667B5472E98CA5B7E /* sr-Latn.lproj */, + 6109B697F6B52FD7D66B26A351F6A920 /* sv.lproj */, + 945357ECAD83195AA46CE7BEE8C52071 /* ta.lproj */, + 6ADA72465BC54012D2E01EF0E369AD84 /* th.lproj */, + F4CAD44EEAACE1ED06ACA9EE0BA5A69A /* tr.lproj */, + 4B57B1D12A80733844C26CC43FC19593 /* uk.lproj */, + 163D0E58B78F8F26B3921C24D10FE991 /* ur.lproj */, + BE2D05806F5FFBEDF2E3296B2922BC7B /* vi.lproj */, + A2FB2B9B3D118E4042071207EAD6153F /* zh.lproj */, + 0E2FDE1552CDE29E8BEE17FA5D661B3B /* zh-Hans.lproj */, + 65FC5F7A295C348696803A456B61FBBF /* zh-Hant.lproj */, + 868E02358BA6AC33B570F4302DD9FE18 /* zh-Hant-TW.lproj */, + ); + name = Resources; + sourceTree = ""; + }; + 797A511120E0FD959787E0D4125B4B4F /* FirebaseUI */ = { + isa = PBXGroup; + children = ( + A027DD8C2432F379A3EDEBF22479042E /* Auth */, + 82A17274EED67E8406D9930D60FF9FB4 /* Google */, + A40D5E6206D64372DC8A0930A818883F /* Support Files */, + ); + name = FirebaseUI; + path = FirebaseUI; + sourceTree = ""; + }; + 7FB1529245CDF605C25AF3FE74ABC2FA /* Support Files */ = { + isa = PBXGroup; + children = ( + F8A44483BAAFA67830C281FFEDC4CA4B /* FirebaseInstallations.modulemap */, + 1072480B6864673EECB3B1CB257C0283 /* FirebaseInstallations-dummy.m */, + 87AE5F696B5814E7D5E782404086EC91 /* FirebaseInstallations-Info.plist */, + B01F7EDFE796ECCD43987D342ACF9799 /* FirebaseInstallations-umbrella.h */, + 62E8321425614316CDA53111C50B49A1 /* FirebaseInstallations.debug.xcconfig */, + 3D5C7F511F0129F1612DE2D4A8CE947B /* FirebaseInstallations.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstallations"; + sourceTree = ""; + }; + 82A17274EED67E8406D9930D60FF9FB4 /* Google */ = { + isa = PBXGroup; + children = ( + C612507BFEF47D61B5266674121F2A68 /* FirebaseGoogleAuthUI.h */, + 76514376A644F1C0AAD24B289F8F5F35 /* FUIGoogleAuth.h */, + 3BF88DFDB9B0042674BFDE9F60D51C7C /* FUIGoogleAuth.m */, + 1F87FC372EF5BD730F3C2367FCF82A09 /* Resources */, + ); + name = Google; + sourceTree = ""; + }; + 870CE55C19CBB8AD6C219A7F2F0D094B /* leveldb-library */ = { + isa = PBXGroup; + children = ( + 7D1C0142C1B858F367068429A25E9A45 /* arena.cc */, + 1C3CA4F92C08777AF6CB0CC107100639 /* arena.h */, + D2933987BB6A2053504823F17604CAFE /* block.cc */, + 62D83D6764BFFF792BDF8BCD6FA8DC76 /* block.h */, + F28F293116C24E8DF57B232A6D217EBF /* block_builder.cc */, + F54FB7D1F60007DA1DA644E4C0BF61F4 /* block_builder.h */, + C38527266A6D5DDFB333ABB2566D6783 /* bloom.cc */, + CE95DF51DF0284663E849AF264C11DD3 /* builder.cc */, + 2898C5A20C3702B07918D03F9FBB0C3C /* builder.h */, + 7EBE8D30CFE961F27D4DCEF388590C8C /* c.cc */, + A54237B6213E123B38287547B3062207 /* c.h */, + BB721B72DF6ED457D6DA175690F307F3 /* cache.cc */, + 1A62BB8032FBA738F4F2D57C13670651 /* cache.h */, + 86A61AF98CFC730742F2497D6BD3094C /* coding.cc */, + A270BC478BF1E34A0FFDEE765533F5D3 /* coding.h */, + 0C29E6056C2E52C3272F5DBF03A284B7 /* comparator.cc */, + 7EB6C4F707D6AE247061BDE99F5582DF /* comparator.h */, + C24569803038905A315E8886A49F56C5 /* crc32c.cc */, + CA29C0CFDAD423D0106AAC1D67A0170D /* crc32c.h */, + 4CC5AD85024AEFCE15D5BB20FF5DE604 /* db.h */, + 49628C5F8E59FEC789DFD126F5FCB1A3 /* db_impl.cc */, + B5D26B5B77EF3AE1B591E57CD37A8A72 /* db_impl.h */, + 34B5C51512525AB5568CAA468C878994 /* db_iter.cc */, + BF8A0755D032262E220C5286C9CCF2CF /* db_iter.h */, + 855E8833CCE10619B411301B970C1A9F /* dbformat.cc */, + 678B1223F2BE90B1D127AB412F334E22 /* dbformat.h */, + 12A895F05CE634F89A21DA41783A9423 /* dumpfile.cc */, + 8AF57F015004BABC4B46244296756737 /* dumpfile.h */, + 3D67CC9E38C38BB28F7D6453E84A0E1B /* env.cc */, + 636F5649D4AEAEE24280A6B1209EADFC /* env.h */, + 960C38CE31171CABDBD3DCD719DC79DF /* env_posix.cc */, + ED1556AF5E4C2B9B1D3F5307AB569547 /* env_posix_test_helper.h */, + 27556724AA71C3E4CA6F469D53BF1EEE /* env_windows_test_helper.h */, + 0540204F58B685F054530616C561282B /* export.h */, + CEFFC93E93A7DC5787D5DF680C4AE458 /* filename.cc */, + 670E3A3782427E916EB9BB0D0B681559 /* filename.h */, + B52ECB24B1A93B2993DBF10DE2DA98B5 /* filter_block.cc */, + 48914A7BA911F9F5780304712CAA8770 /* filter_block.h */, + F01F346D4AD11A343B839A4C4244BB53 /* filter_policy.cc */, + 4B7D65B60CA4A510AF8323E801381667 /* filter_policy.h */, + BC664C1A73AF5E0E4D8D49709109472E /* format.cc */, + 82048231EF2E3884801064A817757265 /* format.h */, + 855CE6FFCB03AA76B086DD233B1F03BE /* hash.cc */, + 5E5F5A39D1BA88D7C06015AD44FDE98F /* hash.h */, + ACA0CE3201D296FEA1844CED6E9D0E8D /* histogram.cc */, + 70F7778B9B8E61DC442DCB0479E095B5 /* histogram.h */, + 78E779BCE9ACE526BBCA1D359975D546 /* iterator.cc */, + 6403E384584CBFB8805D55588F538224 /* iterator.h */, + EEF97A03248B0CEB94C0A83B2825E8E2 /* iterator_wrapper.h */, + FFA39FBA8960A7E7D4BE2CB4087A52A9 /* log_format.h */, + A6D4918D8DF4FD0507640613DA81CC4B /* log_reader.cc */, + AAA93E7250E2606BC3CE32C1BCD11A51 /* log_reader.h */, + 742472618BFECC201CA07F8853313A60 /* log_writer.cc */, + 6BBAD787550D738C9C7AC6091D67E8E4 /* log_writer.h */, + BF78F6F7E220218B75FDE0FF75690CAA /* logging.cc */, + 7CA5F3D7DC34FE7C993F9CDB4D26F4DD /* logging.h */, + 55736272F08581E91E4043F8CE9E5C23 /* memtable.cc */, + 9C8CF2EC8254BD9488FC31DE753FDE52 /* memtable.h */, + ECB5A800627C88957FA98B1987378A64 /* merger.cc */, + 031EB143A6EDC569B9AB682402960F1A /* merger.h */, + 68AB9C81F35DB8A4DCC516175E1F860C /* mutexlock.h */, + 385F5602994D5DE9145DB82DBDBBECB8 /* no_destructor.h */, + ED2CF6CBF8074DC1BD4979852C0F034F /* options.cc */, + 24C2DE86CB1BC54A75C3E5D22F13585F /* options.h */, + 96FD8C25F5D68FCD5169FC2E6D0B9C50 /* port.h */, + 787252786CD85DC82A24166F78BD4E85 /* port_example.h */, + A54588AA46CA9135DA6EA1DF67064247 /* port_stdcxx.h */, + 402DDDB7F31C1C5CE3C227D44A4DECCC /* posix_logger.h */, + A081B6423331628EACC4D7A73AE127F1 /* random.h */, + 6B307FF8DD426613C9E87912E8096331 /* repair.cc */, + E20B04EEB401E2EA11B710895B87E3F2 /* skiplist.h */, + 0BF58E7BD20A582ADA2FE78D5B00B44D /* slice.h */, + D94FE53E1C3A87669A08349FFCB1A1F9 /* snapshot.h */, + 30CA6D91A8DDF03C7513D55329FD774C /* status.cc */, + 614FD0C542050D26FA76C49E96603020 /* status.h */, + 674D53C4BF02A9ACA05F1A27000C5EF7 /* table.cc */, + F59468EA40FA729BFE3CD9A8006CFBEE /* table.h */, + 1B2164BDA4D418A43841726EE9530F9B /* table_builder.cc */, + 32286A49973172FDDFAAEF75ECA6EEDE /* table_builder.h */, + D7918CAF17ADB04CA0D829A49A5E2583 /* table_cache.cc */, + D9C51A32FED68D67E048C2F602C45FE5 /* table_cache.h */, + FB67B500FD9B4600EC2F304EFDA38590 /* testharness.cc */, + 4CAC46B5F4A304C75A40CC264D52033F /* testharness.h */, + 0A6735AEC88EBDF9980427BEC3A16C7F /* testutil.h */, + 9EF93A47B978CDA02A82640CB31708FF /* thread_annotations.h */, + 6CD6E75538335D0C15F77F90238740C8 /* two_level_iterator.cc */, + 48B6C0DC5B6FA45680468DD2690747C7 /* two_level_iterator.h */, + 6097D15BF93E3419D955BD573255BC7B /* version_edit.cc */, + 0F25C53B0BE44DB7561861818BF846CF /* version_edit.h */, + 39FCF7E01DE23C18562782A5899B4D4C /* version_set.cc */, + B70A99DE047CDFD48AEAF4818A9AA25B /* version_set.h */, + 4C634386C4AF3FD1EBC5CEFEF84C46AC /* windows_logger.h */, + 3EEAF9534B473AD61A7AB54C40B9FEF1 /* write_batch.cc */, + 253FA02F3380D6F05F561C4A97AC5623 /* write_batch.h */, + F8267B5FBB4E05B085FAA667C3AE0B4E /* write_batch_internal.h */, + 9184AFCD78AD5C2672F1EC121855C84E /* Support Files */, + ); + name = "leveldb-library"; + path = "leveldb-library"; + sourceTree = ""; + }; + 8789451A1D0C09E582670C9DC247F6A5 /* Support Files */ = { + isa = PBXGroup; + children = ( + 63BC3D605717332C4ECED77F0680FF1A /* GTMSessionFetcher.modulemap */, + 469ADEDE390A439862C502366722D677 /* GTMSessionFetcher-dummy.m */, + AF66366B4FE39EE44F0D31C2EB1B1232 /* GTMSessionFetcher-Info.plist */, + 35BA381B397060FDA499255FBF1E626D /* GTMSessionFetcher-prefix.pch */, + BDF753A2E9438074A71EB24C6EE3B5A7 /* GTMSessionFetcher-umbrella.h */, + 6969333C9227391D15AC78F611999F9B /* GTMSessionFetcher.debug.xcconfig */, + 5269D9C7D55A1DA1FED6C3B459D98F96 /* GTMSessionFetcher.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GTMSessionFetcher"; + sourceTree = ""; + }; + 879492504AED2709213D167F6E2045F5 /* Support Files */ = { + isa = PBXGroup; + children = ( + 109D4BE629EBB055BB466DE4AF91C32E /* GoogleDataTransportCCTSupport.modulemap */, + 5674BB3E7376B13F3BFA81723D39ABC5 /* GoogleDataTransportCCTSupport-dummy.m */, + DEBA9D21F61A5BA2ED8516CD1A9AD43A /* GoogleDataTransportCCTSupport-Info.plist */, + 8D1522D9A59FBC064607570F12367743 /* GoogleDataTransportCCTSupport-umbrella.h */, + C6A572D31316806D9DE6D2194E98FBE0 /* GoogleDataTransportCCTSupport.debug.xcconfig */, + D8E51FA8CD9E9B5E68B3EC07F9539215 /* GoogleDataTransportCCTSupport.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransportCCTSupport"; + sourceTree = ""; + }; + 87EC8C2EB82B82E132A012528AFC0AB8 /* encode */ = { + isa = PBXGroup; + children = ( + ); + name = encode; + sourceTree = ""; + }; + 883FD55E7C24CE6086BA74B020221271 /* Support Files */ = { + isa = PBXGroup; + children = ( + EF2CE305347F3A55862365A41D0F7E5D /* AppAuth.modulemap */, + AA19D221880B1D318DD890057CEBF1F3 /* AppAuth-dummy.m */, + 6CE086BF840833A55297E114A06C1101 /* AppAuth-Info.plist */, + CBA708B893BBC717AC514C1090F7E389 /* AppAuth-prefix.pch */, + 95FA9C91714169BCFFD60B45C1E46863 /* AppAuth-umbrella.h */, + C48ADF74490C4A45C87650023E850992 /* AppAuth.debug.xcconfig */, + 451DB994D279FCD5DC50A8225E9DEDAE /* AppAuth.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/AppAuth"; + sourceTree = ""; + }; + 89569272841C0FF05B46467EF195732C /* Core */ = { + isa = PBXGroup; + children = ( + F816F516E077044050B35F73606B9143 /* GTMSessionFetcher.h */, + 654BB45670AA13C68A7FBDF787179FBF /* GTMSessionFetcher.m */, + D6E3C4C5F3AD43FEBF6E81A4964001A8 /* GTMSessionFetcherLogging.h */, + 413021A56F2BD5431D883E691672D672 /* GTMSessionFetcherLogging.m */, + 0B7DE22D7576368040FBF615532A0DA3 /* GTMSessionFetcherService.h */, + FC2A2B517E03A8347DD866AB5D8629EC /* GTMSessionFetcherService.m */, + 7553C3CCF22589D84A1833B82BD7B112 /* GTMSessionUploadFetcher.h */, + 36CA67D99FD590B97C671527224321D3 /* GTMSessionUploadFetcher.m */, + ); + name = Core; + sourceTree = ""; + }; + 8C4CAF7339451603223C2E075C028051 /* GoogleDataTransport */ = { + isa = PBXGroup; + children = ( + 3A26EC884A9999B199DC3FAA4137C4AB /* GDTCORAssert.h */, + A3E2C01DD82DC9DFC1C6679BEB9F35E1 /* GDTCORAssert.m */, + 6AD16C64DC57BE00921DFB26B3E88660 /* GDTCORClock.h */, + 9646F23A0D4521DB88A49AE6ABD164D8 /* GDTCORClock.m */, + CFF7FA3C082DDECFA0AAD760E36D8078 /* GDTCORConsoleLogger.h */, + 03B2F71602C9A737FACA970FCE8F7BD7 /* GDTCORConsoleLogger.m */, + C47465A0B2EB8E8D479EAC036DD13898 /* GDTCORDataFuture.h */, + C1F6B850C4D596D278B785A539B55B1E /* GDTCORDataFuture.m */, + 766A6826F51D60F3F8BF5907E443E340 /* GDTCOREvent.h */, + F7FD5A9390F75691B9442F5ADA1BA075 /* GDTCOREvent.m */, + 5A149ACDFEA3E4EA95378607B77D3B83 /* GDTCOREvent_Private.h */, + C7618A96808C4D7CEB9824787ABB4DD4 /* GDTCOREventDataObject.h */, + 8F7D6DB45BC5F0FC8039D5B4B9655B28 /* GDTCOREventTransformer.h */, + E7116A9977F9F821C626236E9AF7F5DA /* GDTCORFlatFileStorage.h */, + F3DF5AF9462B5AC7A7232B374178407B /* GDTCORFlatFileStorage.m */, + 2BFCFAAC8BFE82A214A763FFC468F8C1 /* GDTCORLifecycle.h */, + 02B3AF231CF542962F689F76E52481E7 /* GDTCORLifecycle.m */, + EB55F12741576DE36520DDEB0C6B041F /* GDTCORPlatform.h */, + 622905E4C7B48388FBFAEB5B4885A636 /* GDTCORPlatform.m */, + 89891420777E264E545EE3102D324C80 /* GDTCORPrioritizer.h */, + 7941AC0839A2D5B716F6C262BA452CF0 /* GDTCORReachability.h */, + DF253DFDBF8A328A69C50E35AA66F7A9 /* GDTCORReachability.m */, + 44D9AD5C042BBE2D118A698A9E5E76EF /* GDTCORReachability_Private.h */, + 280EEC179686C8D6A48F523385E2A95E /* GDTCORRegistrar.h */, + 6A639DDDCACAA82EDEE506C4020EF5A3 /* GDTCORRegistrar.m */, + 26CCE65941065E0C84C417825219AFB5 /* GDTCORRegistrar_Private.h */, + 06AE775865E552A747572F5608D9863A /* GDTCORStorageProtocol.h */, + 5E1B0586B157A28B1F1A35C9E6783268 /* GDTCORTargets.h */, + 9C927FF92EAEBC5B576C5C5ACD1BFA00 /* GDTCORTransformer.h */, + 83B54EDA0B44A3B61BA9E8304A43868A /* GDTCORTransformer.m */, + BD266F211E48CEE436ECB2082049DFAF /* GDTCORTransformer_Private.h */, + 48FAFEB26DDA963B5ADB9B5659C279A4 /* GDTCORTransport.h */, + FA139674819FBA9C94F5375AC3D9C06D /* GDTCORTransport.m */, + 84B8016FA7491959E6CEBA3C1A3E0E22 /* GDTCORTransport_Private.h */, + D5BC3E7F58942D74E36BDFA2CE60CE9A /* GDTCORUploadCoordinator.h */, + 303AEFF4641C47112E439DB5513D8778 /* GDTCORUploadCoordinator.m */, + F74DEF883FF6125F49131BC4DF11C125 /* GDTCORUploader.h */, + 584DB4080DC999B0DF412672F047EB69 /* GDTCORUploadPackage.h */, + 110B6B1D764C872D7748B1386AF6E5D0 /* GDTCORUploadPackage.m */, + 6617BF2CDA7A9B322A0459463CD349C3 /* GDTCORUploadPackage_Private.h */, + 0318A5FEF1987622B3803E57493B9BD9 /* GoogleDataTransport.h */, + E7F64EEAD0226A4FD1F5480D00E0ECD1 /* Support Files */, + ); + name = GoogleDataTransport; + path = GoogleDataTransport; + sourceTree = ""; + }; + 9184AFCD78AD5C2672F1EC121855C84E /* Support Files */ = { + isa = PBXGroup; + children = ( + F72E90BEC7A0042936C7066EFF232E52 /* leveldb-library.modulemap */, + EC3E413A78DA754C0EC5E48FFCBE543F /* leveldb-library-dummy.m */, + 214BBB5E706185291198C7A134E4DB40 /* leveldb-library-Info.plist */, + 9B88966B5383F85545E1AAFBB02C4726 /* leveldb-library-prefix.pch */, + 07EFF1CBAC30ED458104AF65FAFE793E /* leveldb-library-umbrella.h */, + F405BDCCD96FE6F1912403A62DAE2B04 /* leveldb-library.debug.xcconfig */, + F3F5B906825D61484CAAA87789BD98D5 /* leveldb-library.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/leveldb-library"; + sourceTree = ""; + }; + 91A41D6F85DF700F80B2215D8B9ABF5F /* FirebaseCoreDiagnostics */ = { + isa = PBXGroup; + children = ( + 98E076D44BAA2867EABD71555B9ADF26 /* FIRCoreDiagnostics.m */, + A97A1D0B0968B8B21FB213A4A8E8AD35 /* FIRCoreDiagnosticsData.h */, + 4B507101B953E5884032D7D3E1792371 /* FIRCoreDiagnosticsInterop.h */, + FB9F8446BA7A0A522EE8B2B922D07A7A /* firebasecore.nanopb.c */, + B9C76868E9938C4102BD1215FD5A8374 /* firebasecore.nanopb.h */, + 3FDC7886E20278CBF745C468C159B128 /* Support Files */, + ); + name = FirebaseCoreDiagnostics; + path = FirebaseCoreDiagnostics; + sourceTree = ""; + }; + 9541EBE607ECC6CB0E9E74DE1E34C2FD /* Support Files */ = { + isa = PBXGroup; + children = ( + C9918A4D64494ADCF2E748DEA552D263 /* FirebaseAuth.modulemap */, + 92F0DCFFD953EC71FCFDB3666D6EA0F4 /* FirebaseAuth-dummy.m */, + 6C60370C2CB15E233982FF3A8D8E310E /* FirebaseAuth-Info.plist */, + B49FFCD7B5EBFCE7B830557C601A9F0A /* FirebaseAuth-umbrella.h */, + 0F948F6E03F0241D6A276C287317A33B /* FirebaseAuth.debug.xcconfig */, + 462E033744D3959BB491ED645DF42A70 /* FirebaseAuth.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAuth"; + sourceTree = ""; + }; + 992BEF555EDF920C929910AF6D14080F /* Support Files */ = { + isa = PBXGroup; + children = ( + 325AFB4CBACC98A3F8EC79BF19DDAE61 /* Firebase.debug.xcconfig */, + BB4C2140E68F6C9C0DA2ED701FC0DADB /* Firebase.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Firebase"; + sourceTree = ""; + }; + 9A1D937713BDB35616D1ABCBB5BA4A65 /* UserDefaults */ = { + isa = PBXGroup; + children = ( + 6998105EDEDFE89C9237A903E13AA4AA /* GULUserDefaults.h */, + 25FDFB1572CA5FEEFA8354414A37A218 /* GULUserDefaults.m */, + ); + name = UserDefaults; + sourceTree = ""; + }; + 9C9D8F2BD2C8206E5610C0C480F4E1B2 /* Support Files */ = { + isa = PBXGroup; + children = ( + 98E737E02BDF5544C7E4CCC8C2207DBC /* FirebaseDatabase.modulemap */, + C38D7625DDE875B5097AAC4D90B1F41D /* FirebaseDatabase-dummy.m */, + A86AE5BDDF81D3355108EB4D4CE575DA /* FirebaseDatabase-Info.plist */, + 5A17A81DAC159F24CE9466BA8B0DE04D /* FirebaseDatabase-umbrella.h */, + 78DA4E0D7190329C4F87CE06689EF217 /* FirebaseDatabase.debug.xcconfig */, + F31501F6FF6000C04AC321C6A82873AB /* FirebaseDatabase.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseDatabase"; + sourceTree = ""; + }; + 9F881D75365894A62DF70BC4EE49EBB3 /* Pods-MyExperiences */ = { + isa = PBXGroup; + children = ( + 6692BB174C22B5549DEEF4BC2AF49C6A /* Pods-MyExperiences.modulemap */, + B014CCA1962E1AD28F0B09CE411EB360 /* Pods-MyExperiences-acknowledgements.markdown */, + 7DD45737EBC43DFABAA9FF8C8070FFA8 /* Pods-MyExperiences-acknowledgements.plist */, + 50869C4A83B8711B77611300BCA59CB6 /* Pods-MyExperiences-dummy.m */, + 9C323A9CB167C308F134470280417C15 /* Pods-MyExperiences-frameworks.sh */, + 421A6056036673D61E690E9EAFD6A930 /* Pods-MyExperiences-Info.plist */, + 0A848E3033A143373574E05527F9066C /* Pods-MyExperiences-resources.sh */, + D4B1169E73887E37BA13394C51E86E9D /* Pods-MyExperiences-umbrella.h */, + 7F6F1EC69708D5FC3C78D21BD2150788 /* Pods-MyExperiences.debug.xcconfig */, + E6E77D4731AF3B4301FA924924F6AEE6 /* Pods-MyExperiences.release.xcconfig */, + ); + name = "Pods-MyExperiences"; + path = "Target Support Files/Pods-MyExperiences"; + sourceTree = ""; + }; + A027DD8C2432F379A3EDEBF22479042E /* Auth */ = { + isa = PBXGroup; + children = ( + 572768369632698FD67E08A6CBE5E65F /* FirebaseAuthUI.h */, + C4E8A02EA89196599EEA4611A384C74A /* FUIAccountSettingsOperation.h */, + 03299E70B14A8CA0CD3B288F7D43BE4A /* FUIAccountSettingsOperation.m */, + 9C74A51246137BE63D7AD4A74D0FD7D9 /* FUIAccountSettingsOperation_Internal.h */, + 0FE79FE50D4F48F8C58CB949DBE4AC0D /* FUIAccountSettingsOperationDeleteAccount.h */, + A536C5536C394A6E8669C73E0EB32186 /* FUIAccountSettingsOperationDeleteAccount.m */, + 9B54C1685D4AACE5220DAA13C8DAF23A /* FUIAccountSettingsOperationForgotPassword.h */, + 38DFC526013A1EB3ABF8DE3A65E8E47D /* FUIAccountSettingsOperationForgotPassword.m */, + B11DCFFDC5B68C637EBB08CCE356ADFF /* FUIAccountSettingsOperationSignOut.h */, + 371F7C2003CB9DDACB528B7500A18ECB /* FUIAccountSettingsOperationSignOut.m */, + 6747BE4442C95908D4D28E8D1ABFAB76 /* FUIAccountSettingsOperationType.h */, + 87174475F1969D1150949EC200E43A9E /* FUIAccountSettingsOperationUnlinkAccount.h */, + A024BF1A97EF24A2E139DAE4E26A7246 /* FUIAccountSettingsOperationUnlinkAccount.m */, + 66572644FE511ADF1DD46C07C47BB895 /* FUIAccountSettingsOperationUpdateEmail.h */, + 5F76DC8A393D84B5EC545F11C33B1C04 /* FUIAccountSettingsOperationUpdateEmail.m */, + E53A609A8D12173636B10864238813E6 /* FUIAccountSettingsOperationUpdateName.h */, + 5EDAFAAD07C262D444664C5BD399E6FC /* FUIAccountSettingsOperationUpdateName.m */, + CC5FC2B13E49CF3005150C72BB9FAA4F /* FUIAccountSettingsOperationUpdatePassword.h */, + 428A36C062A2962BC3100F2C0FC17BB3 /* FUIAccountSettingsOperationUpdatePassword.m */, + DB0CC50DFD83B710854E5FB52D9DA568 /* FUIAccountSettingsViewController.h */, + 18E84252C8BBFC1F7C570CCCEA4B789D /* FUIAccountSettingsViewController.m */, + FE6DF75AC07EAEEFBBE8B2D16DA1929E /* FUIAuth.h */, + C7797DEC71A199778D2E303EE512CA30 /* FUIAuth.m */, + AC4C5100114EE4AD832B2C059B9B0B9B /* FUIAuth_Internal.h */, + 234F4C1B718C50970467A34598D11AEF /* FUIAuthBaseViewController.h */, + 953494A16560D8217BD92077C174DEA4 /* FUIAuthBaseViewController.m */, + 31D97EF3B9821B7290206D1CC3E1440B /* FUIAuthBaseViewController_Internal.h */, + 1AC5C1368897ED0DB6D31746B4B0ACC8 /* FUIAuthErrors.h */, + 6301E5CDD1DED7CBC74026B7B30735C4 /* FUIAuthErrors.m */, + 9965D14C5646EB689F1143289D36CDB5 /* FUIAuthErrorUtils.h */, + C8819DA241A028BAD9315C60199BE863 /* FUIAuthErrorUtils.m */, + 3C045B91D80FD301D382461F3767A8CD /* FUIAuthPickerViewController.h */, + E2DAC755661CCCACE7BA1813A316E3FA /* FUIAuthPickerViewController.m */, + 35A44EC21C676A28BC2A89DDC04107F9 /* FUIAuthProvider.h */, + 5C363F15AA606162F501DEC2F1C3F71D /* FUIAuthSignInButton.h */, + A80721995C6E55BC9F26D235F75157BC /* FUIAuthSignInButton.m */, + FF280DA876648901D57970E5E26947C0 /* FUIAuthStrings.h */, + 376319FF589FAE9CFBD2895D95DB64AD /* FUIAuthStrings.m */, + 6CA945041134FF42600B03386818A62D /* FUIAuthTableHeaderView.h */, + 51B79EA8514AB2DE5FB6E83BADD37011 /* FUIAuthTableHeaderView.m */, + 7082B9449622F069DA6D80470872D467 /* FUIAuthTableViewCell.h */, + 4730405FFEC430182522451A957E885E /* FUIAuthTableViewCell.m */, + BD85954CCC85183D912107A4874B556F /* FUIAuthUtils.h */, + 7C3645F8ACEB96B24FFEE072C49B858A /* FUIAuthUtils.m */, + 2A7DC61A346E675EE6ABAE77C84599E6 /* FUIPrivacyAndTermsOfServiceView.h */, + 26EB1333BCF8E07CE70BEC92753A775C /* FUIPrivacyAndTermsOfServiceView.m */, + 34194FA899C7983A97CFA1667E3666D9 /* FUIStaticContentTableViewController.h */, + 5E3B3028D10F8D06C2A88AF313F76CDC /* FUIStaticContentTableViewController.m */, + 9CA4F38D6112A713AD3F9140E7F68026 /* FUIStaticContentTableViewManager.h */, + 2F6BF72CB8650A8FFE6D0E969D4AF6B9 /* FUIStaticContentTableViewManager.m */, + 788D72AE3787A270B8003B3F4A11763A /* Resources */, + ); + name = Auth; + sourceTree = ""; + }; + A32C3A652E1476C6C4DED494B4E56EEE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1D5504A5FE446BDC72CA754CF944A4C9 /* GoogleAppMeasurement.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A40D5E6206D64372DC8A0930A818883F /* Support Files */ = { + isa = PBXGroup; + children = ( + 978D9CD5FC2DD944D7B8A6F1FA1332CA /* FirebaseUI.modulemap */, + B224DAD75F17390167B044A8AC13A27A /* FirebaseUI-dummy.m */, + CFECDB2901F99E856524A436F0735545 /* FirebaseUI-Info.plist */, + 93E345CDC9AD0E97100D7EB33EC1D156 /* FirebaseUI-prefix.pch */, + 0390D03D2B6A00354D273E01C6ABA200 /* FirebaseUI-umbrella.h */, + C6CF3BD228981A8B6F7FA16F10B7BE6B /* FirebaseUI.debug.xcconfig */, + E92379D905E987E03974E31D4B6F3488 /* FirebaseUI.release.xcconfig */, + 8FA5000DD7FFCB9CB4D8C8E26F0B142F /* ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist */, + 80582A0611F09855A38F9572F5DAAFBE /* ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseUI"; + sourceTree = ""; + }; + A614E727274FB818C69C66EC8751DB5E /* Frameworks */ = { + isa = PBXGroup; + children = ( + C8811E8ED5B4CA6329322D2ECD3D3AEA /* GoogleSignIn.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B9188FE8C4B4A0B97D2C82BE0D07F6CF /* FirebaseInstallations */ = { + isa = PBXGroup; + children = ( + 74A271C15E69BBCEC463F5F670300BA1 /* FIRAppInternal.h */, + CDFA7D192C54AC5633BAC1203D5FB145 /* FIRComponent.h */, + 1AF78B774DA999F5D69F23DCEDDC29DF /* FIRComponentContainer.h */, + 79A25A30BCAF35ADC592EE18444941D9 /* FIRComponentType.h */, + 6FC01874018CA0C937F043AF841B3189 /* FIRCoreDiagnosticsConnector.h */, + 99E2BC6EBB91C9FFC6F7A11D13DC86AB /* FIRDependency.h */, + 1C02CBFECE78F11F07A8DC5E7561F36C /* FirebaseCoreInternal.h */, + FD4A9A5E7A8A9588DF99DB175B94644E /* FirebaseInstallations.h */, + E0DAEAF751077AFB2147091AB7D8CEE8 /* FIRErrorCode.h */, + 18B8C3ED9FC01D4F3116710E7ADBBBEA /* FIRErrors.h */, + 61DACD2C6A7C9F8A229EF0ADE870DE2A /* FIRHeartbeatInfo.h */, + 3E9941705FB79B209ED37BD90A5D902B /* FIRInstallations.h */, + 1C9F8DDC9502A6EE00DABC661FA82ABA /* FIRInstallations.m */, + A7B327A0258B05487FBCADDDB623B798 /* FIRInstallationsAPIService.h */, + FDBB301A94F6610BADD69F289B58408A /* FIRInstallationsAPIService.m */, + 8ACC5CF4825F2AD7C86F0B0739E82CC7 /* FIRInstallationsAuthTokenResult.h */, + 2CEEFBDAF3FAAECFB109E6E0B60D19DB /* FIRInstallationsAuthTokenResult.m */, + 5C26D6616E92CB6CEF0C796513A00E7D /* FIRInstallationsAuthTokenResultInternal.h */, + A251FCAE5F4EAAEB842779316E4F5C02 /* FIRInstallationsErrors.h */, + C18E3D1267F99711A68A8B02BF9FFDD7 /* FIRInstallationsErrorUtil.h */, + 65E368CF321942CE98AAD10B26D0A07D /* FIRInstallationsErrorUtil.m */, + E94487BBAAF18F4F350804E397EF0748 /* FIRInstallationsHTTPError.h */, + EB41C29425BE808F8982F4294DDD5D1E /* FIRInstallationsHTTPError.m */, + 45D210693C8C1852BEDCE2218C997AB2 /* FIRInstallationsIDController.h */, + 7BA768461B023567D35A1231C542EC87 /* FIRInstallationsIDController.m */, + 0A854E381D55BE2A7E3E8AABADB04EBE /* FIRInstallationsIIDStore.h */, + C9B6A09B272C1AF4BC48955E6BB468C5 /* FIRInstallationsIIDStore.m */, + AA58215224CE0D047281492EBBA3216C /* FIRInstallationsIIDTokenStore.h */, + 6F86A1C28C6AA54FE5D0809FF096D7FA /* FIRInstallationsIIDTokenStore.m */, + 76F71A018847DEC561975C4EADA9A9F6 /* FIRInstallationsItem.h */, + 9F4106304CD7FCBAC9D6A0DCB765AA54 /* FIRInstallationsItem.m */, + A78967BAA83809158FF45AD8D7E55402 /* FIRInstallationsItem+RegisterInstallationAPI.h */, + 861BCD20A2A3B56F580C7A5CA766DF8C /* FIRInstallationsItem+RegisterInstallationAPI.m */, + BE4803EBD15BE98DB688A0189ECD4ED8 /* FIRInstallationsLogger.h */, + 13E8EE1DCB09BF77593099C551FC273C /* FIRInstallationsLogger.m */, + 5219D7E4DCD40901B20474422BEB8E0D /* FIRInstallationsSingleOperationPromiseCache.h */, + 69F8D7A867F609C67B74BB85FF357F12 /* FIRInstallationsSingleOperationPromiseCache.m */, + F64CE77C106A717D67E4CDE515D39305 /* FIRInstallationsStatus.h */, + 2891BDA51C2AF6BC9404F4A7B1727870 /* FIRInstallationsStore.h */, + 544356950C800EB743CC174C9ABFCCE8 /* FIRInstallationsStore.m */, + 76C1B4F4BBB24C931633B0FBBA0B87F5 /* FIRInstallationsStoredAuthToken.h */, + AE454B37B7F5959A0D2816E4BAB48C6C /* FIRInstallationsStoredAuthToken.m */, + C85496CC24BDC7756948ADF2E7D60E04 /* FIRInstallationsStoredItem.h */, + 0FA4D3EEB0242AE4F3CCF1D1B12BB2D5 /* FIRInstallationsStoredItem.m */, + 2B2E268A97351C2CC543523DFDCB9F94 /* FIRInstallationsVersion.h */, + 27F625BC0D3779D8A1792FFCD42550E0 /* FIRInstallationsVersion.m */, + DAF42C313DED2C3D2F5F3C5156B732A6 /* FIRLibrary.h */, + BDB88ED4C4E94AA853AEA687BD141AC8 /* FIRLogger.h */, + 1B646542193B39A1752CBECC2CFB5F39 /* FIROptionsInternal.h */, + 7FB1529245CDF605C25AF3FE74ABC2FA /* Support Files */, + ); + name = FirebaseInstallations; + path = FirebaseInstallations; + sourceTree = ""; + }; + BD50BD6EAE02459B170706B437CFA2B8 /* GoogleDataTransportCCTSupport */ = { + isa = PBXGroup; + children = ( + EF9FF3D787B018F3B85A15958455551A /* cct.nanopb.c */, + 795CBFB69FAF7FD49AC3054E91F5ED2A /* cct.nanopb.h */, + 9C75CA0EA947F458A55BC7558B99C325 /* GDTCCTCompressionHelper.h */, + 858E389F4C5941E87CE495D9F4C3F1D5 /* GDTCCTCompressionHelper.m */, + 2AD6E35DDB2EE9EE7ABB6F3C84BC29B5 /* GDTCCTNanopbHelpers.h */, + 54C343323DA324F133310E331A56EC54 /* GDTCCTNanopbHelpers.m */, + D5FBD9CA1599240429F1765EBF7ED323 /* GDTCCTPrioritizer.h */, + 2F2239DC0B4B631FF8BCEFB670B66FD4 /* GDTCCTPrioritizer.m */, + 4F423EDD6CE2FAB275E51626151E9B5B /* GDTCCTUploader.h */, + ADCE0BC750EA080093025FC468D756B3 /* GDTCCTUploader.m */, + F514CF18463C2B267F4B21CE743FC308 /* GDTCOREvent+GDTCCTSupport.h */, + FBC075A76606AA21175616AD5D5A2818 /* GDTCOREvent+GDTCCTSupport.m */, + 879492504AED2709213D167F6E2045F5 /* Support Files */, + ); + name = GoogleDataTransportCCTSupport; + path = GoogleDataTransportCCTSupport; + sourceTree = ""; + }; + C46F5570359184A9B021E28DD471FB8C /* AppAuth */ = { + isa = PBXGroup; + children = ( + 53D1D5B885D8DB77D31ACD2A834BBE51 /* Core */, + 2712AD7DB88E460F312299F7F7F70881 /* ExternalUserAgent */, + 883FD55E7C24CE6086BA74B020221271 /* Support Files */, + ); + name = AppAuth; + path = AppAuth; + sourceTree = ""; + }; + C490CE49827E177AF0DFD2536067A2A1 /* FirebaseCore */ = { + isa = PBXGroup; + children = ( + 96164D8ACC099570AEFE2AD13C866D21 /* FIRAnalyticsConfiguration.h */, + 96F59E405A529746B24F54B8A9CA58FA /* FIRAnalyticsConfiguration.m */, + 18A7C0C0F3FDF3AEAF2C3758A25AFD61 /* FIRApp.h */, + 8ED22E829FF20FF3C96668710289B582 /* FIRApp.m */, + E2E4137B3D3CF49006A9C9F46396C872 /* FIRAppAssociationRegistration.h */, + BD30BDBFF431CB4399110E9416A8E470 /* FIRAppAssociationRegistration.m */, + 6D5B40554AE06250C3560A070E872FD2 /* FIRAppInternal.h */, + 79DC4E4C9D18B8167EC254230731F98F /* FIRBundleUtil.h */, + 058B86FB42735EFF6012341A73CFD1FF /* FIRBundleUtil.m */, + 2FA08E7E33E3A732A355057DBAD35E45 /* FIRComponent.h */, + 953C2D3F948748A2BD8EA7A019A49819 /* FIRComponent.m */, + 5007EEBF4BE55DB72D5EE4CAA00E4C5C /* FIRComponentContainer.h */, + 3A64636DD51D9160A5B0AA9214A30129 /* FIRComponentContainer.m */, + E3D90122FAE5E38A814CFE89844E5604 /* FIRComponentContainerInternal.h */, + 81B6701477B6C985CE39D787B599F110 /* FIRComponentType.h */, + F2AF2A78A3B183DE0016FB7675B21129 /* FIRComponentType.m */, + 493BF9F147B5C3D81A03760D93753452 /* FIRConfiguration.h */, + 38DB566120E8E842EE7213F780372006 /* FIRConfiguration.m */, + 9CEA234D8D45743863BF4E8BDB6ECA14 /* FIRConfigurationInternal.h */, + E799655A87365710A1EB972B120BAE90 /* FIRCoreDiagnosticsConnector.h */, + DC32670B925412C8F39FD6CAB0A08327 /* FIRCoreDiagnosticsConnector.m */, + 4FBDA9871C1CC5320359E77952F468C2 /* FIRCoreDiagnosticsData.h */, + CFAAD0E22DA01E9DCCA50AD43C753D9F /* FIRCoreDiagnosticsInterop.h */, + 5A4A40F06A6A8E619437AE6C82A30FB8 /* FIRDependency.h */, + D7FBF775D2A98B0943509C6C0492F77D /* FIRDependency.m */, + 2C32CD26CE098C26904AAD088DBBA4C6 /* FIRDiagnosticsData.h */, + 3206E36B58AC84FF7A082C1E27882B90 /* FIRDiagnosticsData.m */, + D15C1FD503313790B31F95082523E068 /* FirebaseCore.h */, + 984741AB13FDFAE0FBB3AEADA04EDBBE /* FirebaseCoreInternal.h */, + C824D703137DD9400773104180604FD7 /* FIRErrorCode.h */, + 55921E5AC59C99C61E45F4771E6881C9 /* FIRErrors.h */, + 1B851A17E68A633AC605EF3F4D6C2A38 /* FIRErrors.m */, + ED968492E27C084864021919F783D1FF /* FIRHeartbeatInfo.h */, + 09D08393443CCDD8CF77D6023BAAC3A4 /* FIRHeartbeatInfo.m */, + 93F4E2727B989CA69B54F7395BCF5716 /* FIRLibrary.h */, + A9FA51204A20C57FD2FB2EFDBFFE3B61 /* FIRLogger.h */, + 1E003F27645520032E3624A30B1B9E93 /* FIRLogger.m */, + 8DBA967F5DF73F8FE98398812A2958BF /* FIRLoggerLevel.h */, + A2417F4287F02A9B7CB860818E067D32 /* FIROptions.h */, + 5FD82FD67806944740A8EA55D55E725D /* FIROptions.m */, + 1A8D7D0BBB9B7971147224F4CC49B258 /* FIROptionsInternal.h */, + 676A757F81831B5D12A3413072F772B1 /* FIRVersion.h */, + 275B5FDAECAB2575C5E82DA5E44D88CD /* FIRVersion.m */, + D9EEA1C687AB4CD875C2F7500D51A89F /* Support Files */, + ); + name = FirebaseCore; + path = FirebaseCore; + sourceTree = ""; + }; + C714A757F5D99060E46ABC3ED56FBA2B /* Pods */ = { + isa = PBXGroup; + children = ( + C46F5570359184A9B021E28DD471FB8C /* AppAuth */, + 019E979A0BD29BD5BE26961DB955B9E0 /* Firebase */, + 58857F73CBE4944EC40BAE40C6F729ED /* FirebaseAnalytics */, + 581F5860A8A785C1848BFB367ADBD83E /* FirebaseAuth */, + C490CE49827E177AF0DFD2536067A2A1 /* FirebaseCore */, + 91A41D6F85DF700F80B2215D8B9ABF5F /* FirebaseCoreDiagnostics */, + D38A8D3FA4585E7B7C6E64C5E82EB703 /* FirebaseDatabase */, + B9188FE8C4B4A0B97D2C82BE0D07F6CF /* FirebaseInstallations */, + 29CB7B36A9770799F2CB78484DF627FA /* FirebaseStorage */, + 797A511120E0FD959787E0D4125B4B4F /* FirebaseUI */, + F236B5D4272B8BFF7B564582CAA84E4F /* GoogleAppMeasurement */, + 8C4CAF7339451603223C2E075C028051 /* GoogleDataTransport */, + BD50BD6EAE02459B170706B437CFA2B8 /* GoogleDataTransportCCTSupport */, + 596C51AED19D744E168FF87149B3DD01 /* GoogleSignIn */, + 3A97A70077F1F646976B16CF07F2DDB4 /* GoogleUtilities */, + 4FFEC88D8C8E418DA583D7ECDA0EDC74 /* GTMAppAuth */, + 107E41B29C1C3C9658E3185F9CD1576D /* GTMSessionFetcher */, + 870CE55C19CBB8AD6C219A7F2F0D094B /* leveldb-library */, + 1E1910FE64FF8B78D45F08571A70EE6B /* nanopb */, + 2C7236482012FD427A5DF1CBB6F225EC /* PromisesObjC */, + ); + name = Pods; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 0DED8E1D95D61E4D5C5C4DC1454FF079 /* Frameworks */, + C714A757F5D99060E46ABC3ED56FBA2B /* Pods */, + 147DB21F2D8647751EAFCF3213D751A5 /* Products */, + E392BA50F23E039F4EC47B0A4B920DAC /* Targets Support Files */, + ); + sourceTree = ""; + }; + D38A8D3FA4585E7B7C6E64C5E82EB703 /* FirebaseDatabase */ = { + isa = PBXGroup; + children = ( + 12687F38DDA65406B56C297FA9B2EE9B /* APLevelDB.h */, + A896F717F028A846414875FFEE157568 /* APLevelDB.mm */, + DE3C6C8B7895242C8B7E1A4EF84D3273 /* FAckUserWrite.h */, + C35B22038D2BC9F2DD0326DB7D408CD9 /* FAckUserWrite.m */, + 7A8163F1A18B941E2293A680A78F8EBC /* FArraySortedDictionary.h */, + C391CAD9145F4C9DB23A38E59BB34A20 /* FArraySortedDictionary.m */, + B0C9BF1BD3D64D58780FCF7D993843EA /* FAtomicNumber.h */, + E1D60FC645DFC56A7D6208D4B434C4F4 /* FAtomicNumber.m */, + 45E11AF46771013BD558C58EA9770182 /* FAuthTokenProvider.h */, + 7ABD2BED9DB9379A85F50B0F047351FC /* FAuthTokenProvider.m */, + 8A44D696F2163787D7CA8EF6B66B3B29 /* fbase64.c */, + C0B11264065182D6FAD716FE09C948EE /* fbase64.h */, + 0B82EF8025DA0FBD0188AD9F091FBB70 /* FCacheNode.h */, + 2DB63E002E064E3C55D0852F18F0139B /* FCacheNode.m */, + CFDAECD713E8EE3C5428D7BCBF22111C /* FCachePolicy.h */, + AA16A2EC6DEB773205D80D76F235DE58 /* FCachePolicy.m */, + 7D08AD02B34E13ED754D40A419127430 /* FCancelEvent.h */, + 1D8CC6D3E8DCFA0BC10D29F0D214F685 /* FCancelEvent.m */, + D191AC962BC4DF1A4C9B41B31D176C69 /* FChange.h */, + 15C962C270CF2E0D68ACC36DDF996B77 /* FChange.m */, + 663809FA696517E7EBFAD50E9D78AD48 /* FChildChangeAccumulator.h */, + BE6ED932E7AAD7F346281275A45DC1B7 /* FChildChangeAccumulator.m */, + 2F3F1CA3592AD79DF78A58DD1CCFBBAF /* FChildEventRegistration.h */, + D26F148081403A34009C3E64571BB81E /* FChildEventRegistration.m */, + 3E1FAFA86993C6014868FA31E61087E0 /* FChildrenNode.h */, + A99C7A8E7DC4E7B780CCBF06E6C3EF8A /* FChildrenNode.m */, + 01233744AC84606574A5754E9A96964E /* FClock.h */, + 5E73E913D6BE2187678163C216DF1BB5 /* FClock.m */, + D00558C0328CCDB118481BC1BB4058F2 /* FCompleteChildSource.h */, + A7B7105386F708B8C130FB1781D4A137 /* FCompoundHash.h */, + 05767D0A7CDA76A6FB22D66FA268BFF6 /* FCompoundHash.m */, + 1E9E8BC8EA3AD45E32FC2E6FD0DFAADB /* FCompoundWrite.h */, + FCFAA95BB50A7A1D10B42814FAE412EE /* FCompoundWrite.m */, + 2D67FC5FEB279446C5CFB3287D38A9DD /* FConnection.h */, + 5B9D467DDC47ABB6AB58578D530578AB /* FConnection.m */, + 6F5C88B3CCB1162C269594E5A4400834 /* FConstants.h */, + D2614520CA43EA86616C7D7EF35F49E9 /* FConstants.m */, + A71D66ABEC259E383B47228B948294EC /* FDataEvent.h */, + 504B0D1BEED943ACA979474FA55362FE /* FDataEvent.m */, + 38C591D4DAB923A59C4FB29164568937 /* FEmptyNode.h */, + C2108C3AC4A847D23C1CED0BA5C0EC93 /* FEmptyNode.m */, + 847467AF5025D6B485DB432C7B7581C2 /* FEvent.h */, + 368C961A58263B15D8230CEE52FB897B /* FEventEmitter.h */, + E5D4C62D339CFF2B64B65C4480F11094 /* FEventEmitter.m */, + B6BD3FBBC2A8E810BCD6B7AD16D08BCC /* FEventGenerator.h */, + A3D121E26C7391B5D7DB696193E9698F /* FEventGenerator.m */, + 9CD80825846CFECCE10B535583137409 /* FEventRaiser.h */, + 25BCAC05D5A21C8998618E7016194613 /* FEventRaiser.m */, + D320ABBA071441793237FDCC5BF2906A /* FEventRegistration.h */, + AF4370CCD5C550D5805C9E19ADDBB5B3 /* FImmutableSortedDictionary.h */, + 73A677A14C9FC931B5AD7E2C51F74A91 /* FImmutableSortedDictionary.m */, + A56F42E97685ECB4B0F45C2EAE622DBB /* FImmutableSortedSet.h */, + AFCF7CBD5A6947B40B936E1629C4CD6B /* FImmutableSortedSet.m */, + C877AEB4DB96DADD3B3B880F11E807FB /* FImmutableTree.h */, + 49A415C83A5EB9C040FDD6EEC57B55E2 /* FImmutableTree.m */, + 8652F37C3DC08512EA394530E2F59BC8 /* FIndex.h */, + 68428ACE363E5CFA4816A9F1B21640A8 /* FIndex.m */, + 448F29393FE115605D5CA3B7F9E3C564 /* FIndexedFilter.h */, + 1FE785EE6344006DCC6CCF1EB97E4675 /* FIndexedFilter.m */, + 0C9657B10159A1EF60ADA1CA1B6C1E71 /* FIndexedNode.h */, + 505DC4F2361DB07F86AC3E424C21849A /* FIndexedNode.m */, + 580A2DF400B3703EDDEE080EF2686B80 /* FIRAppInternal.h */, + E23E05F6789EEAA15EACA16603FBC88A /* FIRAuthInterop.h */, + A2FB23E8BFBE90DE7FC2150F1FB132A1 /* FIRComponent.h */, + F3F37DC0D68E2ACE25E446599F0A6124 /* FIRComponentContainer.h */, + A122549B6D85715608C5CBF371E00515 /* FIRComponentType.h */, + 3973CC931936DEF986B63B91514EEE6A /* FIRCoreDiagnosticsConnector.h */, + B2D180E7D85A1EFB4F921E0D6C62060B /* FIRDatabase.h */, + F379CEF3D2BB9681071028E02F1BD578 /* FIRDatabase.m */, + A2A714EBE8E059F6E1C1162A7AD08015 /* FIRDatabase_Private.h */, + DE0A7C68BE3AE4D9CF9E2C1E46DD5AC2 /* FIRDatabaseComponent.h */, + F05F10A2D2CB88848EEE94089569B421 /* FIRDatabaseComponent.m */, + 31F1C186A4EAC68717CA9A6D6AE22852 /* FIRDatabaseConfig.h */, + 34FC53C97C18D26AB932C5045350269D /* FIRDatabaseConfig.m */, + E0E399D7C90DB8709C4D6B4C695505BB /* FIRDatabaseConfig_Private.h */, + DBE2AF1FF99BA0861976B62FD7FD819E /* FIRDatabaseQuery.h */, + A2A5A1EE7BFC5AF902EB876693194B98 /* FIRDatabaseQuery.m */, + 085975BA993F8543295A94EECBDD6ECF /* FIRDatabaseQuery_Private.h */, + AB8D15C266FE082A037570E11AE0AE14 /* FIRDatabaseReference.h */, + 78A9978BE5C233D164CD7C226805A2D0 /* FIRDatabaseReference.m */, + FC5C52298AD31598C0A44EF9B2C6F44C /* FIRDatabaseReference_Private.h */, + 706EA4C9C7E61F24F7B8DDB2437C8F9C /* FIRDataEventType.h */, + 3B8F0DF9464867C7A2D721321F226F49 /* FIRDataSnapshot.h */, + 079E3CAFC7164BEDEA7B74133125300C /* FIRDataSnapshot.m */, + EAB5C1025B15D6E3DC47C7BB0A984BC3 /* FIRDataSnapshot_Private.h */, + 32A025FC7AA44B6340F0B3D3ECAE5675 /* FIRDependency.h */, + A4C16C9132307023FAF3F4A82725766A /* FirebaseCoreInternal.h */, + 8CC90D6F4005C5FBF64F12F2C50BA755 /* FirebaseDatabase.h */, + E8F4C1D122F022ACE1D89ABFFF55CA0E /* FIRErrorCode.h */, + DD6E7DB7F56371C9D91F90EC3F06B43D /* FIRErrors.h */, + 1B49E6C76268B31F8E5AB9787C649111 /* FIRHeartbeatInfo.h */, + 81947381D2EAFE5DAE6EB80D863358BD /* FIRLibrary.h */, + 32EB05EE903C50A94CD83EE48DC0E872 /* FIRLogger.h */, + A81FD5C759061AA4B7F4E981E801C9BB /* FIRMutableData.h */, + 8AEE4F8D71B44E0B56E0871B80A32DEC /* FIRMutableData.m */, + EE82A376F70C60AA9E73076A0E27ABB2 /* FIRMutableData_Private.h */, + 144230DCCAA8A18DA6384E2CBB093FFC /* FIRNoopAuthTokenProvider.h */, + 463D1EAEEBD47D9938BCF8A662DC6A86 /* FIRNoopAuthTokenProvider.m */, + FE43939DA337EF2714620503CF0ABD71 /* FIROptionsInternal.h */, + D05CA2DAADBBCFD2217247BCBCD077D4 /* FIRRetryHelper.h */, + D6139A789A449EA83DA37F5C9FF5DD77 /* FIRRetryHelper.m */, + F003A93336794A794BCBCD679CAE6F9C /* FIRServerValue.h */, + 912B58F48447E074A2D77B3BDB573ABE /* FIRServerValue.m */, + AAD4D44993BA05A2CEEDCFB4AEF3E45F /* FIRTransactionResult.h */, + CAD238E59070BFF625623ECA05A24EBE /* FIRTransactionResult.m */, + 21BF9FC4620C4B9524CE633385AE1764 /* FIRTransactionResult_Private.h */, + 54A0D35E86F62F0B4BD48A8412384F5A /* FKeepSyncedEventRegistration.h */, + AD0A6CCE189FE94F37994AAD4CB73A1B /* FKeepSyncedEventRegistration.m */, + 533A075CC6706D52D274E374A6C5F9DD /* FKeyIndex.h */, + 60D6EAE2214B51D9C890BE3365E0543C /* FKeyIndex.m */, + 2ADF4BE0B984457784EB53A44B4AE301 /* FLeafNode.h */, + 34E09E61F0F6E3E1246806D150640883 /* FLeafNode.m */, + 7C3D34F30D5AC628C0E88C3FDE526588 /* FLevelDBStorageEngine.h */, + 213BBD3DBEF0184BBDFCEB20FF14F4EE /* FLevelDBStorageEngine.m */, + E1827EC28E1568C4E60FC36319763CBA /* FLimitedFilter.h */, + 710C93802B6DFF2AC35E8AA400C51F01 /* FLimitedFilter.m */, + 719D94D75C5E235B7C3E2F38110E1402 /* FListenComplete.h */, + 8469477C787E65AC4DECFB61629C330F /* FListenComplete.m */, + 917C3FA5633CF0BC4302E35ED0133084 /* FListenProvider.h */, + B5B759E77F07B7A43FB5DFDE3AEBCD33 /* FListenProvider.m */, + 95171A26BA94A2DC6A9774AFE265085B /* FLLRBEmptyNode.h */, + 69734D4AD914CB4493F17184D49AB7D6 /* FLLRBEmptyNode.m */, + 7C73C0921C9BCBB67271CD840F1E8552 /* FLLRBNode.h */, + D5C4CD5C56186305607180E61C480F0C /* FLLRBValueNode.h */, + 9E8E8A2ED064D9D1ADB6E5DEBAD99AB7 /* FLLRBValueNode.m */, + E2A358A42E48E791E99164F4A01D034F /* FMaxNode.h */, + D16DC9E195D3C24653FD42E36D93874D /* FMaxNode.m */, + 6AFC363CB444A494A51C8E1CF891B276 /* FMerge.h */, + D20FAB51BF2E33A9F29B6692D52010B4 /* FMerge.m */, + 34EEF89628756CF6DADFCF6F7FEF044C /* FNamedNode.h */, + 3785DF72C6DCAF47AE366F2829ABEDF0 /* FNamedNode.m */, + 570063252316BB9DC95F50B0BEC2AE1C /* FNextPushId.h */, + F23F6A10C23DA53CA0245A145EF508AD /* FNextPushId.m */, + BCA966424292F2B2B3A4A968426A30E7 /* FNode.h */, + 3ECDE361BF011270F99FEB1A9A3B6FE9 /* FNodeFilter.h */, + D569EBF0B43DFF73C4402B67F722476A /* FOperation.h */, + EAAE124D4FDC12A2A98D95D218A42E38 /* FOperationSource.h */, + 01B5588E52D3B11F82A0D7F0C8DDAF9F /* FOperationSource.m */, + 2AA9752886E774984AD2D35449B849E7 /* FOverwrite.h */, + 2C90A57F312058F5070F24619DF2D4AC /* FOverwrite.m */, + 8D643088290FC363A90F847070973A68 /* FParsedUrl.h */, + 26A701B9267F7E760B27DF5EFD4E534A /* FParsedUrl.m */, + DD9D94B4A4AE84B510828A2C92D89819 /* FPath.h */, + FC7E3FA7EA5372B5C2C86F26E4BE5033 /* FPath.m */, + D4DC8D9D0355EBB0F68A676013F799AC /* FPathIndex.h */, + 2F122A33B14CBFBDCBB14223CE8EDD41 /* FPathIndex.m */, + D2DEEA5B92D2B175ECEDC2E2557D596A /* FPendingPut.h */, + 4D4712F06B0944FE3AF1EE789281B047 /* FPendingPut.m */, + DABCC02033CB02917A53BDE950562EF9 /* FPersistenceManager.h */, + 3975E8FFC67926A0E8DD39BDCBA4B16D /* FPersistenceManager.m */, + 3321CB5DB4DF1C493E717FC8351C71A4 /* FPersistentConnection.h */, + 2CA5B41F52E3B66856135E15CC4759A8 /* FPersistentConnection.m */, + B0382A72B82D98EB0659D080E198382F /* FPriorityIndex.h */, + A7AFBD062FA62F077ECC87E01A4138FC /* FPriorityIndex.m */, + 9FEC1F12EB515DFCF19288525A7FBAE6 /* FPruneForest.h */, + FF680DFC00216365C48B4199252AEB01 /* FPruneForest.m */, + AAF8E5F6347530C455055D47E32788FE /* FQueryParams.h */, + 4CDD262BE955BCCD50139C26B4E1B37C /* FQueryParams.m */, + D55CA217A8FE4CCD968B2FB20090140E /* FQuerySpec.h */, + 93350B3059FFA3016BE438DE54C68169 /* FQuerySpec.m */, + B37F5E42FA68448CE182756873C9A2CC /* FRangedFilter.h */, + 3C891BDA225BAD436CEF7AF7F1695ACD /* FRangedFilter.m */, + 1405A82BE0B36A65A6E5B9FA9BBECE56 /* FRangeMerge.h */, + 64F0158D39427082A58B66417D642EF2 /* FRangeMerge.m */, + AE90B3E6EEC9E3BF861BA8A809F7298D /* FRepo.h */, + AF966A01B41EB868CD964B1A909147EB /* FRepo.m */, + 294612EF265084E263D9B8EF81CEF4FC /* FRepo_Private.h */, + 207EDF36E35871F4F9C7108E522E144F /* FRepoInfo.h */, + 71B0ED66B3AB0DEACE07CFB743EF1AB1 /* FRepoInfo.m */, + 2639674FFC61B91B6BC5DF9392EBF3DD /* FRepoManager.h */, + 85F1F6036F7E1CBEF9C35C3689DE4CAE /* FRepoManager.m */, + E708ADE62264AB03AD82509CD7E587EF /* FServerValues.h */, + D977A66079935F32A4225D1C90E2615B /* FServerValues.m */, + 6FE49F161741365656721C78D4163690 /* FSnapshotHolder.h */, + 94186DE3D7783AF3D30A3B3D37ABB931 /* FSnapshotHolder.m */, + 865D3B59B3F895B75DB12A7B67131BB3 /* FSnapshotUtilities.h */, + EB92407015693027CAA3FDAFA73D9004 /* FSnapshotUtilities.m */, + FA971777AE9035EA63091527E76D1AF1 /* FSparseSnapshotTree.h */, + 3FFE94EC5AF860B62041D69B5EE9486A /* FSparseSnapshotTree.m */, + 64FDB8B8A3BAEE7F4E9AF31419F79891 /* FSRWebSocket.h */, + 41C974DAB5B079CE71E75DB13DFC0CC7 /* FSRWebSocket.m */, + 8C76C26999C5EBBF7EA157465C0939D5 /* FStorageEngine.h */, + 2952573EE05F206F04E91F8CE6DBE770 /* FStringUtilities.h */, + 8BF46F360C12AAC644A4E6A1F433F683 /* FStringUtilities.m */, + 5E16797E9464DC13C0026A832D0C8518 /* FSyncPoint.h */, + E34AEFBD4E8EA4B3B004C94CAA3C78C1 /* FSyncPoint.m */, + 24FE7022564CEAD1E6D3E5E23E421FC5 /* FSyncTree.h */, + C6B3A10FE7BA9E0E113004E04AB0D9FA /* FSyncTree.m */, + A526C31FD98918B4CE3A59BB0BD27C90 /* FTrackedQuery.h */, + 9237CE067B92CC661714D1430998DA2D /* FTrackedQuery.m */, + 104E98D4E5F9FA4F8720F910348707B0 /* FTrackedQueryManager.h */, + 180AD6EE5C9A774D35CCC09E2C3643B3 /* FTrackedQueryManager.m */, + EB9053EF1ABC9AAFACEFBF5649C58920 /* FTransformedEnumerator.h */, + 8810AE5E10E7D7E8DB0D9B3CB32C0D9B /* FTransformedEnumerator.m */, + 76F463D2321280A211075F635EB82633 /* FTree.h */, + DE334E8A8F2607F9F0CF675028E6CB9E /* FTree.m */, + 69CE82213B430ED4CC3D6630855D6FBD /* FTreeNode.h */, + 1B69E273AC1F848FB9E6B3E2592B78DF /* FTreeNode.m */, + 1888721E3588FD46C7845A8A58070079 /* FTreeSortedDictionary.h */, + 964A6F832C7C75A9B0A0FB580C10E821 /* FTreeSortedDictionary.m */, + EE8D1F47D22F1D6FAA6945CA508BFB12 /* FTreeSortedDictionaryEnumerator.h */, + 406E73A9D34FD1FB8B07E30E058567AF /* FTreeSortedDictionaryEnumerator.m */, + 866CC51076A49B7A5196DCF601092E13 /* FTupleBoolBlock.h */, + 8790E43ACFD7A0F4E4F20D3DE7E249B5 /* FTupleBoolBlock.m */, + AF4EA4512BEB4222E9BFDDF30A07AC8D /* FTupleCallbackStatus.h */, + 113E302B441B981A827DD3B4EF35419F /* FTupleCallbackStatus.m */, + 6365C0AF9225C127A860B57949F71079 /* FTupleFirebase.h */, + F1D52AFE6BB5A995128447A1AF90B5D1 /* FTupleFirebase.m */, + 24191B50B213697BDB0A03CD396569F7 /* FTupleNodePath.h */, + D06BB08F59112DF40E024F3DCB8BA877 /* FTupleNodePath.m */, + CBB066214D917EE5CF525A00A0789398 /* FTupleObjectNode.h */, + 10C804434EE90A3648EAC6407DCF9D28 /* FTupleObjectNode.m */, + 0C8A0A0BC4CDBE2A71CCF4AF70BABC39 /* FTupleObjects.h */, + 18FDC64B1FC85B24ABB1C0364C15D919 /* FTupleObjects.m */, + 505214DCA8CABD3F660E0A6ACD5A60B8 /* FTupleOnDisconnect.h */, + 10414BB146383FB69BFD1324CB140BD4 /* FTupleOnDisconnect.m */, + 4383A93D64CCC99B231FE7ECB7CB0C6B /* FTuplePathValue.h */, + CC316F2270A94C0F8B764AC4D6CE36E7 /* FTuplePathValue.m */, + 7F78C92980B846317529AEE3CAF792AA /* FTupleRemovedQueriesEvents.h */, + 5F642D548971EC7E8066481D6B7AEF05 /* FTupleRemovedQueriesEvents.m */, + 646E13F13038F5392591DBBD166BFDB3 /* FTupleSetIdPath.h */, + EC9F5D9D34F3AFD51FE48B10DCDAE1FD /* FTupleSetIdPath.m */, + B97D7D6E5E4BC068C64A9517329F59DC /* FTupleStringNode.h */, + 838C87E3EEC318432FFA15251F58F8F9 /* FTupleStringNode.m */, + 2C7B84BCD12457E28D8C0A6D55563C32 /* FTupleTransaction.h */, + 716DE49C140CA622BFAF92044E4F1E02 /* FTupleTransaction.m */, + 0D7E8EFB9E99E8AAFEA96ACA4086DBE3 /* FTupleTSN.h */, + 9C6715856AC895328A2AEAFC8B86E640 /* FTupleTSN.m */, + 24C6B81A862144EBBB10A29A617297D3 /* FTupleUserCallback.h */, + EC9A2EB346797982B9ADD669A3C48AF8 /* FTupleUserCallback.m */, + 50678D93A7A086BDB66C72F4A47CC647 /* FTypedefs.h */, + 477B26F19AC7827CEAF7052AEAF4F1D1 /* FTypedefs_Private.h */, + B85875DD11E278FBC02338C96C934B34 /* FUtilities.h */, + C64029352A35B37DDA881D4E6ACF6C1E /* FUtilities.m */, + AB5A9CB8FC820368415F100A55EF934B /* FValidation.h */, + 1CC0A3191504AAE5AC701D8DDF35DB9A /* FValidation.m */, + 39ABF5B68E7A7B653EB64EC5D2D49DCD /* FValueEventRegistration.h */, + C01BC2C5447DFEE202AD31B17BA8FEA8 /* FValueEventRegistration.m */, + DAEE1F42C1FC3226D38F0A8043D355D4 /* FValueIndex.h */, + 9B9627E22602C602EF52BFF49FE56D98 /* FValueIndex.m */, + 907BBDD52C7ED77CC879E7EA2FF71132 /* FView.h */, + 7EB1396AABC1139BB96C6491579BD8F4 /* FView.m */, + CB21872684931D690D8AB43AC75C1930 /* FViewCache.h */, + DF33474F2924572E91E1E1B155DB0BE4 /* FViewCache.m */, + 7E0A008BCE52F3A0574E15041D57A2CC /* FViewProcessor.h */, + 9F27A7A83BC933E0BA0CF7DD8D4E4C81 /* FViewProcessor.m */, + 118374FE49AD27D512B8BA9E44E4B3EB /* FViewProcessorResult.h */, + C6E90123E0824FF1FE9CD046989FCD25 /* FViewProcessorResult.m */, + AA6836C316894F3DD346893242595932 /* FWebSocketConnection.h */, + 2EBC0578E0831E699FDC8C670820885A /* FWebSocketConnection.m */, + 04B732645135CA8B3E7FA00F9C6EDB77 /* FWriteRecord.h */, + B2C1368FD864972A677AA6F00D203E6D /* FWriteRecord.m */, + 62C87D6A9A8CBCDE954AE13FC94E21EF /* FWriteTree.h */, + AF8A2024FCA85F80B0E6A5BE255D7504 /* FWriteTree.m */, + 3B89883354B04E7224B4BCA94DCD089D /* FWriteTreeRef.h */, + AF143C3AEAFA1634232E7FDB22A4A7F2 /* FWriteTreeRef.m */, + 3D96CCF8A1C3B80683E8A3C1767636D2 /* NSData+SRB64Additions.h */, + 9F36BCB3D0BD01DDB626C5FE3F73DFBE /* NSData+SRB64Additions.m */, + 9C9D8F2BD2C8206E5610C0C480F4E1B2 /* Support Files */, + ); + name = FirebaseDatabase; + path = FirebaseDatabase; + sourceTree = ""; + }; + D9EEA1C687AB4CD875C2F7500D51A89F /* Support Files */ = { + isa = PBXGroup; + children = ( + FA544CBD59A051B4A85F775980536364 /* FirebaseCore.modulemap */, + E0A693BC5175C7A316BEAA2AB79D1605 /* FirebaseCore-dummy.m */, + C35495E3A2AE522CF824CEDE83F84FA4 /* FirebaseCore-Info.plist */, + 3E258FDF1B764B343037CC2895777F91 /* FirebaseCore-umbrella.h */, + 0B94E6B8AF33C56D68D4AD9BAA5FEE2A /* FirebaseCore.debug.xcconfig */, + AE31FD42BB2863C4D9CAC980F8085F1A /* FirebaseCore.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCore"; + sourceTree = ""; + }; + E392BA50F23E039F4EC47B0A4B920DAC /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 9F881D75365894A62DF70BC4EE49EBB3 /* Pods-MyExperiences */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + E6F241A0A1E00B3CC0D32DFEBCDF04A8 /* Resources */ = { + isa = PBXGroup; + children = ( + 5400A145F328381BD52F9A9ACF4C7A06 /* GoogleSignIn.bundle */, + ); + name = Resources; + sourceTree = ""; + }; + E7F64EEAD0226A4FD1F5480D00E0ECD1 /* Support Files */ = { + isa = PBXGroup; + children = ( + B3178115AB08280B641E901DDB1BD191 /* GoogleDataTransport.modulemap */, + 3D39D997779449D74727241923F8597A /* GoogleDataTransport-dummy.m */, + 26AE83E15A11B203C7FC6321AEBFA6DD /* GoogleDataTransport-Info.plist */, + A24AAC884CBBE3470180211F88008142 /* GoogleDataTransport-umbrella.h */, + 2BA69B89E7BA669D98FB1669F1953521 /* GoogleDataTransport.debug.xcconfig */, + 12AA880F6A063BFB19894928A16F070A /* GoogleDataTransport.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransport"; + sourceTree = ""; + }; + ED459BF38D565AB1D5FCF41ACA3909FB /* Support Files */ = { + isa = PBXGroup; + children = ( + 961B225F52CE4624C6901942FBDA468A /* nanopb.modulemap */, + 9F6B023A8F096B22FC186C9C8E59C42A /* nanopb-dummy.m */, + 8CAB24B3E0499D3AEFE0BB09F8A193D5 /* nanopb-Info.plist */, + 2FFBB31D3B28EE6DC5C2DAAF84FEA52A /* nanopb-prefix.pch */, + B7EBBBA5B262CA6C018FC09D4BDA7CBD /* nanopb-umbrella.h */, + DF010ADE9F5D95CEA7163C271DF4AF14 /* nanopb.debug.xcconfig */, + 47BF9B1F1B231A09680C4D56CCE235B4 /* nanopb.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/nanopb"; + sourceTree = ""; + }; + F236B5D4272B8BFF7B564582CAA84E4F /* GoogleAppMeasurement */ = { + isa = PBXGroup; + children = ( + A32C3A652E1476C6C4DED494B4E56EEE /* Frameworks */, + 0F6C9DDC3A7409D759418E33B0EDE0DE /* Support Files */, + ); + name = GoogleAppMeasurement; + path = GoogleAppMeasurement; + sourceTree = ""; + }; + F3435E6BF052FF25BDEDE5786AE030B0 /* Full */ = { + isa = PBXGroup; + children = ( + 4255EAE792EEC21FF83A733F61479D97 /* GTMGatherInputStream.h */, + 73A3621A5DB4EDBF660C671792E13759 /* GTMGatherInputStream.m */, + 98C64CF03F4D64D5309F6FFA11432FED /* GTMMIMEDocument.h */, + F060A463E10E778840180D47DF65B53C /* GTMMIMEDocument.m */, + 576B91C11B11CCAE6FF3C083E2910102 /* GTMReadMonitorInputStream.h */, + 792379C88F502528FDFCFE6202E0702E /* GTMReadMonitorInputStream.m */, + ); + name = Full; + sourceTree = ""; + }; + F5FA5811622F93C00EC912C309CB7455 /* Support Files */ = { + isa = PBXGroup; + children = ( + 23EBD84FD0800C9B1C349C22E48EEDFA /* GTMAppAuth.modulemap */, + 6FDC8EC42195FA6009210D0F20D0C85F /* GTMAppAuth-dummy.m */, + 625AF7810C28799EFD82E03BD62AC283 /* GTMAppAuth-Info.plist */, + C1AF546369B668B9AAEA63DF300E02FD /* GTMAppAuth-prefix.pch */, + 7AAD146A75E91278F8462790889BE1D3 /* GTMAppAuth-umbrella.h */, + 813EE38656EDBC2CE28989B9B8E3D86F /* GTMAppAuth.debug.xcconfig */, + 46208F8F4DA72F736C3CA97FBF8633E5 /* GTMAppAuth.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GTMAppAuth"; + sourceTree = ""; + }; + F74DFF2EA954084F51F5A0AEAD994BEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3958033B920F8ED4E9D12BB4DC6794E2 /* FIRAnalyticsConnector.framework */, + C8FB088C56A528C234F4F1E509AF3A15 /* FirebaseAnalytics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + FC629AA5A207E934847DA56D53E02668 /* Support Files */ = { + isa = PBXGroup; + children = ( + B6A87CF7908130E325DFCD7785AF2613 /* FirebaseStorage.modulemap */, + 39720C2178180584478CFED5FB451DA5 /* FirebaseStorage-dummy.m */, + 9B232AAF44021458D2D8894666F9EB80 /* FirebaseStorage-Info.plist */, + 9355EE8CB9035164A79720BFC33A56ED /* FirebaseStorage-umbrella.h */, + 6B0125857F5D4327999FD36E51BC633B /* FirebaseStorage.debug.xcconfig */, + C2C0C1E05732AAA942EE2412CFBE94DB /* FirebaseStorage.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseStorage"; + sourceTree = ""; + }; + FEF3AB10B6D5592DD5D72BB51EB413FC /* Support Files */ = { + isa = PBXGroup; + children = ( + 53F0F09CD2905B3297B81557EFD55B0F /* FirebaseAnalytics.debug.xcconfig */, + B2C32D7546A54979C5057A1181763D1C /* FirebaseAnalytics.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalytics"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1057C3C3EFB3A71D0F404924ED9638CE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B8C4453F4A7ABF993101ED40BE8812D9 /* GDTCORAssert.h in Headers */, + 413F760343B563758599EFD78245EFD7 /* GDTCORClock.h in Headers */, + 6FD2F3431F03D1A5C3DE8F1D802A983B /* GDTCORConsoleLogger.h in Headers */, + 6646F7A9030D70C4019BB2316CF337C8 /* GDTCORDataFuture.h in Headers */, + DBA3198737B9A39069EE86B647EA0E5C /* GDTCOREvent.h in Headers */, + D4EDC0B95F72E25E7923D15D0B068EA1 /* GDTCOREvent_Private.h in Headers */, + 441867214FE4F98B0C9F20E21208F7FC /* GDTCOREventDataObject.h in Headers */, + 6DF3B0AAA63BEAFCE7094FB577489D3F /* GDTCOREventTransformer.h in Headers */, + F113B4B95B46B980F23BC35C3C564B07 /* GDTCORFlatFileStorage.h in Headers */, + 83B513BCA178F00372FF0042E59A1759 /* GDTCORLifecycle.h in Headers */, + C9BD79A50C9EC3E798D8EA9743FEB144 /* GDTCORPlatform.h in Headers */, + 0AE9F9F29EB3BB9798F860FDDE3CD3ED /* GDTCORPrioritizer.h in Headers */, + CA21C68AAD82AECD4E74D178D22C4BB9 /* GDTCORReachability.h in Headers */, + 59FEE0211B52A4CCFE5DB2179A01FF9B /* GDTCORReachability_Private.h in Headers */, + C5A8251BA3C2CF37D84FD68E9C153F0A /* GDTCORRegistrar.h in Headers */, + A82B62CE863483B4FB7661341B35378D /* GDTCORRegistrar_Private.h in Headers */, + A58760AD72BC23A29A025E8873D4686E /* GDTCORStorageProtocol.h in Headers */, + FCD759F250B22BE7B29D01149C8216C4 /* GDTCORTargets.h in Headers */, + 504B56632F2230AD3EF1B88DAA787A96 /* GDTCORTransformer.h in Headers */, + 8EF66D6A65E0849321CB79239C8AD085 /* GDTCORTransformer_Private.h in Headers */, + 9F5F67A891539CECE9C1A3285F62719A /* GDTCORTransport.h in Headers */, + 00DADBF26BEF6BD179AE093EC9231CCC /* GDTCORTransport_Private.h in Headers */, + 8A8B1741DD4AFEA9252A0B5FBE02CC26 /* GDTCORUploadCoordinator.h in Headers */, + 30FF3B52E3D4C9C0E207DB078A70666E /* GDTCORUploader.h in Headers */, + 8C7A0D8A352ED75BE526BC8311E6F499 /* GDTCORUploadPackage.h in Headers */, + B81AEE4361D3E800FFD1AC49B81BDD83 /* GDTCORUploadPackage_Private.h in Headers */, + B409B8076034296CA2FA6F4B31E636CC /* GoogleDataTransport-umbrella.h in Headers */, + 7A50620B4C214D8B10974690FAA364CC /* GoogleDataTransport.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 10CE1F5C0EBB29B2200FC8A8DA5957CF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E76B7C34229CFB62ADDDEB8B33806449 /* FIRAppInternal.h in Headers */, + 091E5416619836F280790E6F7FF6A8E1 /* FIRAuthInterop.h in Headers */, + A6241D9B2D4E672378D5F036D1B977B1 /* FIRComponent.h in Headers */, + 5DB69E5C7D55E41ECD5D6F0D8F0A29CC /* FIRComponentContainer.h in Headers */, + A7B9EBEEC714CFA6B00B694ADB2F1CB8 /* FIRComponentType.h in Headers */, + AE289590D289D602BD6BBB20321B6BE3 /* FIRCoreDiagnosticsConnector.h in Headers */, + A8316A4B275335565F9E8CB7552874BF /* FIRDependency.h in Headers */, + 138EB885AE9B8EC5EF961BE4CB222E2F /* FirebaseCoreInternal.h in Headers */, + 8E4A4E11F424D88C0172B4A6CD045FD3 /* FirebaseStorage-umbrella.h in Headers */, + AA10A572E5964B3B12BE4D381B7A62D7 /* FirebaseStorage.h in Headers */, + 624C42CFD7FA7048F3DE883B44C04D60 /* FIRErrorCode.h in Headers */, + 3C2146EE415B38ADD4EF547E5855A2DF /* FIRErrors.h in Headers */, + E5D9CA3A8FD14545EDF531018A012713 /* FIRHeartbeatInfo.h in Headers */, + 0A73B6F3F5E2B453AEF9F687C7D2AC63 /* FIRLibrary.h in Headers */, + CD113573D4CC942C9C7C59F3B33B6A71 /* FIRLogger.h in Headers */, + B02CF31C4FCAF3751BD1ED6C52B06056 /* FIROptionsInternal.h in Headers */, + CD87F97CF807919B1A53E9A690E81C34 /* FIRStorage.h in Headers */, + 55CE468A3EF488AF96C380654BEC4B74 /* FIRStorage_Private.h in Headers */, + 6A1FD1AC578C58BC8A617A0A8606DDF0 /* FIRStorageComponent.h in Headers */, + 6116CA8A83772FCBA115BACC671E5576 /* FIRStorageConstants.h in Headers */, + 5BE34532594B80EFE8E63750EE123CCF /* FIRStorageConstants_Private.h in Headers */, + 447B106C81021B25A65FEB3686397CE9 /* FIRStorageDeleteTask.h in Headers */, + 37465688E43C89C656D5CACBC39A2E90 /* FIRStorageDownloadTask.h in Headers */, + 28C913EE8096746CBB939DA315476F10 /* FIRStorageDownloadTask_Private.h in Headers */, + E0FCD66EBDA02C684788F94AF3B506E8 /* FIRStorageErrors.h in Headers */, + 241723DE0B8689347F719ED670BA6922 /* FIRStorageGetDownloadURLTask.h in Headers */, + 660DC62495C43FFE4D5D1AC2657F8FED /* FIRStorageGetDownloadURLTask_Private.h in Headers */, + 0670F9B0D4BA8C54C8A23C22D9E5618E /* FIRStorageGetMetadataTask.h in Headers */, + 959A3CDB042F5871E0E3AA527133DC81 /* FIRStorageListResult.h in Headers */, + 1F99D3CB1E0A313C9973622AAC67C5D8 /* FIRStorageListResult_Private.h in Headers */, + A6AF52EDF168718FB5AC4607D589F3B1 /* FIRStorageListTask.h in Headers */, + 28A0FAEB4F76BFC6E2B3FF8B9C15F3ED /* FIRStorageMetadata.h in Headers */, + 851880D13DB5D1A93358B1F2AAE060B6 /* FIRStorageMetadata_Private.h in Headers */, + 7F8CDE565E023F5CC2C0861C6D98AD26 /* FIRStorageObservableTask.h in Headers */, + 775E22843AD00704F6C417DDA74CF096 /* FIRStorageObservableTask_Private.h in Headers */, + 8E79BB8C34F8BFD02697676CF726AEE8 /* FIRStoragePath.h in Headers */, + 00CC75B60414D7910BCC30EE254B618D /* FIRStorageReference.h in Headers */, + 7DF36ADB94EDF3053487FC003C8EAFCD /* FIRStorageReference_Private.h in Headers */, + 3746A7ECB545CF4FC344F47B4BEFA1F0 /* FIRStorageTask.h in Headers */, + AA1838ACEF3E00C8B3216AFFBE86FBA4 /* FIRStorageTask_Private.h in Headers */, + 91AA7DB040EF94A27EE34059D7F9B621 /* FIRStorageTaskSnapshot.h in Headers */, + 8E95B6FFFAC285BEE38684A4A7D8E30B /* FIRStorageTaskSnapshot_Private.h in Headers */, + A97592B677E28AEB0899B5F7FBFBCB96 /* FIRStorageTokenAuthorizer.h in Headers */, + E79BC35F5EA6D578733825721321CDB0 /* FIRStorageUpdateMetadataTask.h in Headers */, + 138B814247C78F12A672FBEE055D7827 /* FIRStorageUploadTask.h in Headers */, + B6ECFD8B80DB8001DDEE0DB009FC3A7C /* FIRStorageUploadTask_Private.h in Headers */, + 2ACAF4FD734EE4B2A78BEC5DCE57BEB9 /* FIRStorageUtils.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 12CC7779BFA71300C62FF3D6F904A62C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F0EDE9B2A1C5B429C5FB45DB791CED5F /* GTMAppAuth-umbrella.h in Headers */, + 6230A2FA25019907339AB7E5DFEDD58C /* GTMAppAuth.h in Headers */, + AA17C6D52EBC4DD945C43E225CF32581 /* GTMAppAuthFetcherAuthorization+Keychain.h in Headers */, + 36D9504FDB889AE9A1B4AB4FD576607D /* GTMAppAuthFetcherAuthorization.h in Headers */, + 4F949070B5291E48CF5EE510B4C4956E /* GTMKeychain.h in Headers */, + 8B75BDF535CA2F37FEB50CB6C5549877 /* GTMOAuth2KeychainCompatibility.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 25BAD54C6901DD7866C33A44CAAE3BC7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E2A523C16DD8DFFC23E95AE5A7396B9 /* FIRAnalyticsConfiguration.h in Headers */, + A946BA4157746AA69CC1DAF1232397D5 /* FIRApp.h in Headers */, + 332623A10AD4F5CD55CA20169E654B23 /* FIRAppAssociationRegistration.h in Headers */, + 665CE8BAE7485D20C42A1C8B79B49E0E /* FIRAppInternal.h in Headers */, + C009BF9383B259CD9DEC0B039926C38B /* FIRBundleUtil.h in Headers */, + 1B2359FB213D972B04AB428B73428914 /* FIRComponent.h in Headers */, + 4B2EDDE16EC22B41C5B7E73CBCDC80C5 /* FIRComponentContainer.h in Headers */, + DD19B6905B7D7FA862FFC69BFD07029D /* FIRComponentContainerInternal.h in Headers */, + CD930D588F6D49757B2D862919EB92E1 /* FIRComponentType.h in Headers */, + 6D3EDAD808408B202C2E25BE168E42EC /* FIRConfiguration.h in Headers */, + BB6B02BE21083F91EE3B0785E60A1C90 /* FIRConfigurationInternal.h in Headers */, + A3F18BECA57B9B33FD0735EE363AB67F /* FIRCoreDiagnosticsConnector.h in Headers */, + 9DF45ED125C847BE7A7BBE63A9C5E0B2 /* FIRCoreDiagnosticsData.h in Headers */, + 24D2FE95FC6B50A5C98D0B8039780BE7 /* FIRCoreDiagnosticsInterop.h in Headers */, + A8278716ED8C8E8703B2F8AB2613CFED /* FIRDependency.h in Headers */, + 6C254C11330DAC6125A3DDC7021EDB54 /* FIRDiagnosticsData.h in Headers */, + 1BC76176733CDE9A8DCF1E94651A2C6A /* FirebaseCore-umbrella.h in Headers */, + B03AD60FE916920455F438761A2EA7F4 /* FirebaseCore.h in Headers */, + 5C951A44B81A828A3485F607D8A7C113 /* FirebaseCoreInternal.h in Headers */, + 387BCCCC3FDB1BCECC6B8C541B95B0CB /* FIRErrorCode.h in Headers */, + DC9289D6C939B88D93E2144AB1FE45E2 /* FIRErrors.h in Headers */, + C8E7FFDEA70D91218F9E8A3A58E244A5 /* FIRHeartbeatInfo.h in Headers */, + F8299543C8A7BE4A43BDD63CD33D5057 /* FIRLibrary.h in Headers */, + 8461186C4A4FEB64043D673E667F694F /* FIRLogger.h in Headers */, + EDE7D66D2B5C037707D24A24088DF30B /* FIRLoggerLevel.h in Headers */, + 23D1216C52CD698E9A1913D29EAABC66 /* FIROptions.h in Headers */, + 009E758800055F3BAADF302919166AFD /* FIROptionsInternal.h in Headers */, + C84C5FF8647958F76E37CF4871A38F2E /* FIRVersion.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29A628FE701AF8BAC1D0D5211E5A09DB /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9342E20127EF18C2F8D20091861CC25E /* FBLPromise+All.h in Headers */, + 9BBC2ECD2906A76B3376421FEC2C3C1E /* FBLPromise+Always.h in Headers */, + 84C9CC4035AC423C9CC0DEF3EF0679A1 /* FBLPromise+Any.h in Headers */, + 5BC15725B1ABE70CB2B617F6871F14D6 /* FBLPromise+Async.h in Headers */, + 18D63BE1F3E713E003C5268ED2A02BBB /* FBLPromise+Await.h in Headers */, + 85F2CC4C6E1D8F5AA03361800F3A0C8A /* FBLPromise+Catch.h in Headers */, + 33A030CB4B6202E221D82324542DAA62 /* FBLPromise+Delay.h in Headers */, + 40BC0E0EF1FE17A85517CA882F24ADB2 /* FBLPromise+Do.h in Headers */, + D8145466BA46014F7375DC27A5A1A06A /* FBLPromise+Race.h in Headers */, + 4AB046B92EB84D420565F315B38AE0E1 /* FBLPromise+Recover.h in Headers */, + 1B8EE3F7B7617A196DDD1723A10149E7 /* FBLPromise+Reduce.h in Headers */, + 30005E7E0F75C7836E14CE4B4E621F89 /* FBLPromise+Retry.h in Headers */, + 067099545B3490DB37E9CE7ADB97E22D /* FBLPromise+Testing.h in Headers */, + 1EF66BB9A24839176E1B2E8ACF2E9B66 /* FBLPromise+Then.h in Headers */, + 16543FBCEE63DF8AE41E9AFB0D3B7D6D /* FBLPromise+Timeout.h in Headers */, + 9EAE5B3A6CB274A9C857DB49FC5D0C4E /* FBLPromise+Validate.h in Headers */, + 4F2180FBFFD05BE4EBC767685881881B /* FBLPromise+Wrap.h in Headers */, + 8A56347FABE2C135A87C8DC88DC39A2B /* FBLPromise.h in Headers */, + C6178D7F669409CECF25B71C2FB85B35 /* FBLPromiseError.h in Headers */, + 94F45BDD28B6D698E0FABEFB8C3762DE /* FBLPromisePrivate.h in Headers */, + BBCEEEC509BF6A9787EED2A08B678B47 /* FBLPromises.h in Headers */, + 8FCF84A8B634A87288A82B3087643899 /* PromisesObjC-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39E296290881AABF68B18A19700F158A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A807351D7EDBD43936003A83C5E625BE /* cct.nanopb.h in Headers */, + 810080743EC879A912A46CD2835D95B4 /* GDTCCTCompressionHelper.h in Headers */, + DBE525E02DE2D94E18A9DDA72F7F3BEA /* GDTCCTNanopbHelpers.h in Headers */, + B947E3208B2FFE506E5BF0C2DC866D08 /* GDTCCTPrioritizer.h in Headers */, + 45514530A4C6DF33B53542A269A20CCA /* GDTCCTUploader.h in Headers */, + 8B8829DFC110B8B0D7D0A7F7FA51473B /* GDTCOREvent+GDTCCTSupport.h in Headers */, + E96A582B38DBF7513BFCE5A26FEDBD98 /* GoogleDataTransportCCTSupport-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E7A59CC470AF47F5D93F514201E5196 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 047249349DA6FD3DAE63565A26BF17E5 /* nanopb-umbrella.h in Headers */, + F45DC573E9465E4C95C24C3A7FB7CA6A /* pb.h in Headers */, + D88025F2C3B8216079E481F8B98AAF10 /* pb_common.h in Headers */, + 6435AA398ABD7022725DC4180278829F /* pb_decode.h in Headers */, + 4DFB2DC386C65A06CBE4D5D900B87C38 /* pb_encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4493DFB71B788DB8D7B1F9CDF049D4C0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FB5040342CAAF75666DFFFE139DEDA94 /* GTMGatherInputStream.h in Headers */, + D68C650D4605745F4963E990CA7D3547 /* GTMMIMEDocument.h in Headers */, + 237AAD8D6D9697F75230ED02BD359A22 /* GTMReadMonitorInputStream.h in Headers */, + 9A5C11FEFAF0280F937175CC9114A689 /* GTMSessionFetcher-umbrella.h in Headers */, + 42902A1836055088CB9CE3031ABAB20D /* GTMSessionFetcher.h in Headers */, + 7540C69AC8A0C763556FB85A18AE1AE7 /* GTMSessionFetcherLogging.h in Headers */, + 16C1AA8A28F90B8F5AE061BEA96D8BB5 /* GTMSessionFetcherService.h in Headers */, + 80000D72EB8E257326A757521C8DBBF6 /* GTMSessionUploadFetcher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 469827005540582C6EB83E949481AA5D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F4E5BBECD1B7031C8F00A369BE738842 /* FirebaseAuthUI.h in Headers */, + 5A592B3EC4BC8877387D08796C9A55F7 /* FirebaseGoogleAuthUI.h in Headers */, + B7FBAA203ECBB4D9AC70C22EE1EE9623 /* FirebaseUI-umbrella.h in Headers */, + B25F6CE0F40D81A392EC5E7E28538F20 /* FUIAccountSettingsOperation.h in Headers */, + 58388FB6F90F3E8F46C1B59E8CD02A7B /* FUIAccountSettingsOperation_Internal.h in Headers */, + 28D20A833E7B75D6CC38C07167549BA3 /* FUIAccountSettingsOperationDeleteAccount.h in Headers */, + A1D8C9FAE7C7896ED69973B0957A2A68 /* FUIAccountSettingsOperationForgotPassword.h in Headers */, + C6ED392FABAA1A8D02E565FD8A52F9ED /* FUIAccountSettingsOperationSignOut.h in Headers */, + D44CD3D86EF04A05D44A13F1D20D3172 /* FUIAccountSettingsOperationType.h in Headers */, + 5AC2CDD3C635A465DDA6FD5E9F38BD47 /* FUIAccountSettingsOperationUnlinkAccount.h in Headers */, + E3967DFA258F8BC1453EAC67AE9310F7 /* FUIAccountSettingsOperationUpdateEmail.h in Headers */, + 94E29F5ABD13E2D2FE5170F070B267A4 /* FUIAccountSettingsOperationUpdateName.h in Headers */, + 10BDEE9B0C9281E76BB1078DD2BD5796 /* FUIAccountSettingsOperationUpdatePassword.h in Headers */, + C75EECAFB762933254A481B1087679CA /* FUIAccountSettingsViewController.h in Headers */, + 3E52BA6652B376B3185D2020446B6DD6 /* FUIAuth.h in Headers */, + 7E6CA1344E04CD3082D8EDAD07F61FEE /* FUIAuth_Internal.h in Headers */, + 4092A1D75E185C4A5AFA4BB2CD98058A /* FUIAuthBaseViewController.h in Headers */, + DCC571B18FD701B48BBBCDE7BB8980ED /* FUIAuthBaseViewController_Internal.h in Headers */, + 3B0E9B0B629DF07E6A8AFA719F59A567 /* FUIAuthErrors.h in Headers */, + 17B79354012E32ABDE229A9C9EC52402 /* FUIAuthErrorUtils.h in Headers */, + ECABCEA0F748B3932FEC95A7ECA42B53 /* FUIAuthPickerViewController.h in Headers */, + 76C8D5115AE00C059DEB289AE147B7F3 /* FUIAuthProvider.h in Headers */, + 31CC134F37391AE197C14AF757C26CB3 /* FUIAuthSignInButton.h in Headers */, + 33E51598939F4C04843B589E45A77A94 /* FUIAuthStrings.h in Headers */, + DF36D69235F7E6D1FDB363A72474DA71 /* FUIAuthTableHeaderView.h in Headers */, + 76015C6D9A72F2B002CE9A33C1F78D8D /* FUIAuthTableViewCell.h in Headers */, + F953FD5F7471BF27A56FF74E1CD36529 /* FUIAuthUtils.h in Headers */, + 2B83873DFCA886ED30666E5BCBB58AC6 /* FUIGoogleAuth.h in Headers */, + 77022DA37144CD3FBE165FCEE8C5277F /* FUIPrivacyAndTermsOfServiceView.h in Headers */, + 1B9F33FCAC1A035AC50F41584DE984F0 /* FUIStaticContentTableViewController.h in Headers */, + DF0D854E2FCE940A60925487FE56383F /* FUIStaticContentTableViewManager.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4BC2A1E2B8A2FBB214975D3840B7740E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E443ECCBA3ED60473D807F189C63A0C6 /* FIRAppInternal.h in Headers */, + 5904666A636D27B7AFC0BD1B17300206 /* FIRComponent.h in Headers */, + B32A3AFA04977EF646295A55AE05BB42 /* FIRComponentContainer.h in Headers */, + 056E8F8BDDB1AFF2FBEFE7F93112B495 /* FIRComponentType.h in Headers */, + 9E05210EB198E73CB1A7DADF2D219034 /* FIRCoreDiagnosticsConnector.h in Headers */, + D5CCA75FA6DF1657EE59A5D11C1059D9 /* FIRDependency.h in Headers */, + C894562B59FED9FC11755DA0F9CE9CD9 /* FirebaseCoreInternal.h in Headers */, + EC1E607B0EEF07BB64F476B9FB5A4FFE /* FirebaseInstallations-umbrella.h in Headers */, + 35018015F6FFE61A4F46B65E2845FD50 /* FirebaseInstallations.h in Headers */, + DF469B7659F9DFF3166AB7C7C8887D6C /* FIRErrorCode.h in Headers */, + E8EC7708E95120E14E2961DA89E96899 /* FIRErrors.h in Headers */, + FCDD19997C4A4C655F8E2CCA8BE31E58 /* FIRHeartbeatInfo.h in Headers */, + F4A86F4F47AF4ABB0A8FE4D860226B39 /* FIRInstallations.h in Headers */, + 5A2092F7D72C888A4C9BE7400E7C18B0 /* FIRInstallationsAPIService.h in Headers */, + 43A408791A67AA75FBCBE6587CC3DEA9 /* FIRInstallationsAuthTokenResult.h in Headers */, + B1E49935E84945F6EE24B225CFC278BC /* FIRInstallationsAuthTokenResultInternal.h in Headers */, + 169A74523986554B514943622050DBE3 /* FIRInstallationsErrors.h in Headers */, + 6F4FAEA776D76A65BCB083D627CC06CE /* FIRInstallationsErrorUtil.h in Headers */, + 156146F448852ADD9C9D3B49860DF567 /* FIRInstallationsHTTPError.h in Headers */, + C7289C4F97B6F1A1FB5A7ACFE2138B8E /* FIRInstallationsIDController.h in Headers */, + C1FE53C9812D63B00503FCFE5A73073A /* FIRInstallationsIIDStore.h in Headers */, + 7F99CC65F3BC049F4DD035F3B1E25121 /* FIRInstallationsIIDTokenStore.h in Headers */, + 6F969D63E1984AA64325C08C49EBE9B3 /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */, + 0A3B29ABFB794000DB38123C64FDE483 /* FIRInstallationsItem.h in Headers */, + 5795021557FD78AA2F276AB2493C0A61 /* FIRInstallationsLogger.h in Headers */, + A78549116DDF889C58A9F46898B2B71F /* FIRInstallationsSingleOperationPromiseCache.h in Headers */, + FD40D9F5432F5551E88C9103C3361ECA /* FIRInstallationsStatus.h in Headers */, + F69343F5F4D92D4C742FCAF11C040243 /* FIRInstallationsStore.h in Headers */, + 4E9FD6CD2C6379A3F8365E46CE7AECCF /* FIRInstallationsStoredAuthToken.h in Headers */, + A0BF51881987376BC9B74063328B9AC5 /* FIRInstallationsStoredItem.h in Headers */, + 9F71C538973429360D8A83A31336266D /* FIRInstallationsVersion.h in Headers */, + 61409E53AF384794ACAF6872282AE7A1 /* FIRLibrary.h in Headers */, + 06B3FD4869C8C25A4501C123A0FBE7B4 /* FIRLogger.h in Headers */, + 4AB84171CC0E53C6D2BF6B264EEAE02E /* FIROptionsInternal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 63E4537496312DBA8F8E53E40D1E9335 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6872C9725C60CDB8B44A961B40B6ED66 /* Pods-MyExperiences-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69D968EDF3D8E4D392307035F5EC7024 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 823C53D54E74E675B01DF082CFD5F984 /* arena.h in Headers */, + 7EE8C19AA1A52012EEE0EB873A93F753 /* block.h in Headers */, + 2DEAEDF07164BC2DB28248EDF0971A2A /* block_builder.h in Headers */, + B54C74810389280E1F77C0DBCB1FD458 /* builder.h in Headers */, + 9E4622FC3425305AEEF9CD631E9D7704 /* c.h in Headers */, + BB52C704A0547D78D4B5024FD5C2B26E /* cache.h in Headers */, + 6F8340EF98B0A00DDBAC8D01A80C8A1B /* coding.h in Headers */, + 57D8CE3355759AE954FCF0C0F918E3C4 /* comparator.h in Headers */, + D8F4D4105D327D9DD02B64983C266ED2 /* crc32c.h in Headers */, + 72551A633B093070277BBF1D8EAB7F8C /* db.h in Headers */, + A0D1F0D02C2DB0BEB765658CDF51399F /* db_impl.h in Headers */, + 436A7138CFF866F2575CBE9FF6E4EC23 /* db_iter.h in Headers */, + E469D24D743C3E4652BF03FE14A930A2 /* dbformat.h in Headers */, + D153992C6E00A3A73A591420044ABA6C /* dumpfile.h in Headers */, + 72EFC9D90E0D66ACD54150B700EB5191 /* env.h in Headers */, + 5EE6BE4642CFB50AB022550D59AFEDDC /* env_posix_test_helper.h in Headers */, + 93493AC239D78B1790A850CC1E389B95 /* env_windows_test_helper.h in Headers */, + 9A33B6A9C212905EFDE4C4AACBA0A178 /* export.h in Headers */, + 0F49128C205AF2A2509D53D5579911DF /* filename.h in Headers */, + 0F75CE6137488B705DCF5D0FE9D18D98 /* filter_block.h in Headers */, + B089A1D99D75DFD5AD881E31885F7897 /* filter_policy.h in Headers */, + 53D9A922A43771043C21040DDA0F0DAC /* format.h in Headers */, + 3F87E8F7B86DB236E23F6C3A00501A0A /* hash.h in Headers */, + 804A48A974F3E7EA43E120E1716087E3 /* histogram.h in Headers */, + A4FF7952658AA4749E1203852EAF3EF5 /* iterator.h in Headers */, + 79D8009BEBE725189259C7A9A5EF99C1 /* iterator_wrapper.h in Headers */, + F88E6F2C4272A5079D67CFC2FA86DEDD /* leveldb-library-umbrella.h in Headers */, + F2A52B29F6C03BEE388842FD6FDBA9F9 /* log_format.h in Headers */, + 7468A23BA7000985D721A7C11A520985 /* log_reader.h in Headers */, + 1833D1267C3EA07F8D14FDC36F170E7B /* log_writer.h in Headers */, + 8053A04D3E94C47270DF7E20DC5C2534 /* logging.h in Headers */, + 3B9227E12D80A9D65A23A7B7EF3569A4 /* memtable.h in Headers */, + 911926D9525D10CE088B5472F5CE9AFF /* merger.h in Headers */, + 951A6FBC0536F645BB5713B2D2EC7C4A /* mutexlock.h in Headers */, + CDE4F12CC12B5CFFBF4D04D7575C1F13 /* no_destructor.h in Headers */, + 2949C1B902AB172E5A880292042AC4AF /* options.h in Headers */, + 94D7A47F5D3F7E23F12339B3BEDFF4B5 /* port.h in Headers */, + 6C98BABC3A75D5EF8C3371D2599EDFD0 /* port_example.h in Headers */, + C8B2F117CECE081D514EC94EA9F6E8E1 /* port_stdcxx.h in Headers */, + 0E73740CE03CFFBCF2553BBD03C8709C /* posix_logger.h in Headers */, + E5D3A5F9BD84F3C5F7C52537823DDED5 /* random.h in Headers */, + F567CD8818C2CCF71B31DC02EAAF2049 /* skiplist.h in Headers */, + 794F295EC59C4560E6CCD03EEDA8B66A /* slice.h in Headers */, + 3C4B9FC273F97FDB310FC2073B0ACC0A /* snapshot.h in Headers */, + 5DAEC63FC80477A0171EA77AEAD16BDA /* status.h in Headers */, + 0284D4732B1E2B5E8B7344503C1B1EB9 /* table.h in Headers */, + FDF061B03A01F2FFEB7070BCA968F22F /* table_builder.h in Headers */, + AAB20654E0156F30AAAFEDC0E8E54644 /* table_cache.h in Headers */, + F6FD97488F8B55246A4560D09E895FE8 /* testharness.h in Headers */, + FC6E525DB59C8B750B92BFC9267D4AE6 /* testutil.h in Headers */, + E538ADF57675483F5E819544E3196EB3 /* thread_annotations.h in Headers */, + A9E1D9E34515B7D31A8CC0F95B6B29CD /* two_level_iterator.h in Headers */, + E00843404BB41C185A3A63CCAA29CB08 /* version_edit.h in Headers */, + 3DAF0DCDD6C3F9795DFACBBF4F6CC6AE /* version_set.h in Headers */, + 68DA1592ADD50C6018446F171DBF70F2 /* windows_logger.h in Headers */, + 9C33BADC9ECD2C72DCF4C1AC75C31AAF /* write_batch.h in Headers */, + B6620134F7F9D18E523F1E7634934462 /* write_batch_internal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E758F98F082A7E4050E9F229D1D46B6 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A4DF4AC097E6C5DD3364EE8B68093E20 /* GoogleUtilities-umbrella.h in Headers */, + 0635DC0B0F4725383E83C0427634E26E /* GULAppDelegateSwizzler.h in Headers */, + 537EEE67A109664A97D0D2D59838A10C /* GULAppDelegateSwizzler_Private.h in Headers */, + 12F05C34BFA2A9B171512D29F3657F43 /* GULAppEnvironmentUtil.h in Headers */, + 5E35721415C0903BE370D06334C27713 /* GULApplication.h in Headers */, + B56B41D5962C27D301A1E174A31C222E /* GULHeartbeatDateStorage.h in Headers */, + 90F52BEB687049C2DB0139830075BC05 /* GULKeychainStorage.h in Headers */, + 9FC70D20B3369EE9CBB59C2955C7D232 /* GULKeychainUtils.h in Headers */, + 60E586EEBCC6FFFA26741B26230488BB /* GULLogger.h in Headers */, + D0E7C9A19C43A52F8052381B1D72C5A9 /* GULLoggerCodes.h in Headers */, + 5D018C896E2B857D71EA72830177FFDC /* GULLoggerLevel.h in Headers */, + 560CB000DD26855FA975032136CB0006 /* GULMutableDictionary.h in Headers */, + 2B9C5DC3D19A8C0C76BA6BE665D9D15C /* GULNetwork.h in Headers */, + F682300AAA5CF33F9E4730A6199E483C /* GULNetworkConstants.h in Headers */, + 3887AFED9A7EECCDD1BF72AD99D26EB5 /* GULNetworkLoggerProtocol.h in Headers */, + 14F2303E429FE24F27D5DDABA686B3EB /* GULNetworkMessageCode.h in Headers */, + BB0BEA6B1B8BBBDA8ABE5FDF85171637 /* GULNetworkURLSession.h in Headers */, + 971B32F3642180C9B6249CEAC634F1CE /* GULNSData+zlib.h in Headers */, + A8AD2F68486AC0F2F1F8358BED647B24 /* GULOriginalIMPConvenienceMacros.h in Headers */, + 93B48C27C6C647103C85D3D8A9DE068B /* GULReachabilityChecker+Internal.h in Headers */, + 7725AD47580F7EC6D4D36655133F9E78 /* GULReachabilityChecker.h in Headers */, + 7CCB435518D2A10F1651D67BC5A7867B /* GULReachabilityMessageCode.h in Headers */, + 1B1043A3469C9CCD275480C414D650F5 /* GULSceneDelegateSwizzler.h in Headers */, + 5DE5ACB9424B4D9130BDC8FE8BD41307 /* GULSceneDelegateSwizzler_Private.h in Headers */, + C5066C4DEF6536FD0EFF1FB8817B580A /* GULSecureCoding.h in Headers */, + F19FEAC355F8BD5C7A64542BF3D5AB4B /* GULSwizzler.h in Headers */, + F34348F4E358B24E8905FDA182085DB4 /* GULUserDefaults.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5FCC80568D8E29D856A0FB46A4100F9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 37E7849CC2713E6140E4FAF8421B842D /* FIRCoreDiagnosticsData.h in Headers */, + 69148E8F738D51175109D84DEF186D1D /* FIRCoreDiagnosticsInterop.h in Headers */, + A89E5739575FA08DEA9CBB22657E9B01 /* firebasecore.nanopb.h in Headers */, + FA54A074580C072694058298A88B803C /* FirebaseCoreDiagnostics-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BF20DD677E68B0FFF096FA87BA4F642E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F3D2632F5565AFA96A15FBA9EAFFF410 /* AppAuth-umbrella.h in Headers */, + F677A4A964B9095056DA905477CE4F3C /* AppAuth.h in Headers */, + EE191018EF34395C61D30D78FED87E45 /* AppAuthCore.h in Headers */, + 408352680097A53851035145970371B1 /* OIDAuthorizationRequest.h in Headers */, + A14710681730656A8EE4F2793773C18B /* OIDAuthorizationResponse.h in Headers */, + 013D945A6EB50B6FC9854DE84D18E44A /* OIDAuthorizationService+IOS.h in Headers */, + EA278C7D9EB69B68733EF68A0C150345 /* OIDAuthorizationService.h in Headers */, + 670E2A31490D13725DFB5CBBF08B12EF /* OIDAuthState+IOS.h in Headers */, + 6B2C401E08F2AC0A87453061CA3E8E2C /* OIDAuthState.h in Headers */, + 082620B4CAFF07381D466C7F54CDC435 /* OIDAuthStateChangeDelegate.h in Headers */, + C760F013C47E323D4C9D3E1FF5E34338 /* OIDAuthStateErrorDelegate.h in Headers */, + 4870D0FB963B09D3D9FAA4E3DC9263FB /* OIDClientMetadataParameters.h in Headers */, + 4480D20BAE2A84682B5DE51F51A5DD4D /* OIDDefines.h in Headers */, + 91907BA379327CACDF19EA39EAD05338 /* OIDEndSessionRequest.h in Headers */, + 3BFE8CD59118C4908BDCF67DA762C118 /* OIDEndSessionResponse.h in Headers */, + AA3BE332B851918B23E03F283868116C /* OIDError.h in Headers */, + 617968B11188B95B6117BE9A51BCC2F7 /* OIDErrorUtilities.h in Headers */, + 83BAF0108579702991C01C961439111A /* OIDExternalUserAgent.h in Headers */, + 487B398FF6DE0468B5E8E4FEBB432327 /* OIDExternalUserAgentCatalyst.h in Headers */, + D87549BF6D8F527CF351E13326FCEF21 /* OIDExternalUserAgentIOS.h in Headers */, + 2808F21DE383D3C9BD0DA03A7B95F6AA /* OIDExternalUserAgentIOSCustomBrowser.h in Headers */, + F598CB205564B44BC8BC6B774DEB1B62 /* OIDExternalUserAgentRequest.h in Headers */, + 85AC70140CF3718AA932C21689BF865A /* OIDExternalUserAgentSession.h in Headers */, + DE23788919FF5136AC4B77F9B29FB4C1 /* OIDFieldMapping.h in Headers */, + 40FC84D2AFB6832635DD9A929E516BAE /* OIDGrantTypes.h in Headers */, + 2B268B1D89DDEE445606464B1105E0F3 /* OIDIDToken.h in Headers */, + BBC602EC86EB71FC4ACD5728C9058E23 /* OIDRegistrationRequest.h in Headers */, + E3B32C12184BD887E6687F73097489FA /* OIDRegistrationResponse.h in Headers */, + 8ACA9C8B657C3C149214E3649860AF76 /* OIDResponseTypes.h in Headers */, + 8955CA20EEA55F5D75CDE87F0CADCF83 /* OIDScopes.h in Headers */, + 7ACD06125D4ECC1EC05EAF68B2DC0C99 /* OIDScopeUtilities.h in Headers */, + AE07D07F98D805B39CAAB4E89F1E87B8 /* OIDServiceConfiguration.h in Headers */, + 8417CFCEA12E96E62CFA4A646672BCCB /* OIDServiceDiscovery.h in Headers */, + 355CF2719234ADB11A1993E2120CC373 /* OIDTokenRequest.h in Headers */, + 321995AB5C5DD22B2DC924BC8F2AF053 /* OIDTokenResponse.h in Headers */, + 0B764CD79758A19F877947F521050A30 /* OIDTokenUtilities.h in Headers */, + 39D4516A2DB8E91D2A1C0CDB79BDCBCE /* OIDURLQueryComponent.h in Headers */, + D4E43B95AA2B76BDEC6B97B152F00463 /* OIDURLSessionProvider.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C0F878EB58A135F908E3E26677366E30 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0F2500D0441CC03A2598B059E068660D /* APLevelDB.h in Headers */, + 040398E7E9AB077D7DCBF6E45442DC68 /* FAckUserWrite.h in Headers */, + 266FB1080816C26C4835948DD4C2E547 /* FArraySortedDictionary.h in Headers */, + C4A5292FFAEDC02154ACB30201BFCDBD /* FAtomicNumber.h in Headers */, + D2046623AFEE603E261E417720B645A2 /* FAuthTokenProvider.h in Headers */, + AE892DF714C5A2F1BDB6BDE8CE8599A9 /* fbase64.h in Headers */, + 84767001BF9038BAF82C200D383B33FA /* FCacheNode.h in Headers */, + B65C2A1A1C756F2CC67B7468FE537E75 /* FCachePolicy.h in Headers */, + 97AE873860105489B97DD3495A3C05F6 /* FCancelEvent.h in Headers */, + C108416C60A490E5C1E8AAF7D42CB5B7 /* FChange.h in Headers */, + 249E4080458DE5559E6B676D13B1787B /* FChildChangeAccumulator.h in Headers */, + E9F723EEC8516CA7A483BA6EDC50D8C5 /* FChildEventRegistration.h in Headers */, + 59902A903D69F70D9B5D1A04374AC404 /* FChildrenNode.h in Headers */, + 9920ED7AC41A3FA6E16A6BDB4FF1F1AE /* FClock.h in Headers */, + 9D1AA39AFCDE0D6AD55B0846FA7E59A7 /* FCompleteChildSource.h in Headers */, + F108A35D5F20AAE03C47FDFC7EB8423F /* FCompoundHash.h in Headers */, + D5DB4306E33312DA4BAF9D6295BA225D /* FCompoundWrite.h in Headers */, + 9F431113F61815502B9F771D243A9907 /* FConnection.h in Headers */, + 26D56FF050B6A9CD6ECF65DBC32A0093 /* FConstants.h in Headers */, + ECCA642BC105435BB9D30D8683FB4F3F /* FDataEvent.h in Headers */, + 77B2042023799E1A5CCE2817D26EDDC9 /* FEmptyNode.h in Headers */, + 02780B28FD6A9973F8CE67A844991646 /* FEvent.h in Headers */, + 978E4EDFA4BCA900839C20CC0E60CC30 /* FEventEmitter.h in Headers */, + F26F91FF2BEA275801E9631DA164EF65 /* FEventGenerator.h in Headers */, + 0425D372E9746ABAC18FFA2886EE6534 /* FEventRaiser.h in Headers */, + B37568066FD3EA9B0A9C4749C4FFD55E /* FEventRegistration.h in Headers */, + B1B9D7366A9E4175DC4A545555B169AC /* FImmutableSortedDictionary.h in Headers */, + 640209D1D7B24B1AA144E731BFBE6D66 /* FImmutableSortedSet.h in Headers */, + 9E16F41FE897503F47580345EDFA431F /* FImmutableTree.h in Headers */, + 9B78061B40589957D4C79B090C918185 /* FIndex.h in Headers */, + 2E6B5CAD78D5EAF1C6067E4496107D1A /* FIndexedFilter.h in Headers */, + 7AF9EB305B880930B06D0711FB8DB6A0 /* FIndexedNode.h in Headers */, + 8D0CD9DB407585D44818C6904A3FB6AD /* FIRAppInternal.h in Headers */, + B5C5172BB02980A57FED91C71AD08006 /* FIRAuthInterop.h in Headers */, + 9CBD80B9EC20D09184982C3B1490A6F9 /* FIRComponent.h in Headers */, + 4D2C23B725FFED954CDE8F4DE5DB7155 /* FIRComponentContainer.h in Headers */, + 94401C0ABA0A5CD0A41D09ED83BDC0C4 /* FIRComponentType.h in Headers */, + 1547776673C1A743D3AD20732D62FB04 /* FIRCoreDiagnosticsConnector.h in Headers */, + 877EDB3BD268CDD6D4A1434B65A21FF1 /* FIRDatabase.h in Headers */, + 37DDC4C15E27EB7E2E2A0E852F5429D2 /* FIRDatabase_Private.h in Headers */, + 91F227FA1ACA21C709DA0CF20004538C /* FIRDatabaseComponent.h in Headers */, + A3447593D7E7311E4E94634D138344B0 /* FIRDatabaseConfig.h in Headers */, + 89C5F6C4D72EB3EA22FCD1C29505B584 /* FIRDatabaseConfig_Private.h in Headers */, + 3347C5B0CC6F9D2F6F791ED570E53525 /* FIRDatabaseQuery.h in Headers */, + 3345F3975DD23AFE1A2F4C96F30AFA13 /* FIRDatabaseQuery_Private.h in Headers */, + BECC3E12395C5B73E231B9F4484DCA22 /* FIRDatabaseReference.h in Headers */, + FAA959BBC36AB00E58C4CD4C0020448D /* FIRDatabaseReference_Private.h in Headers */, + 17D33ABE5E7B27EADA2DA3D0543D9D17 /* FIRDataEventType.h in Headers */, + 92AA5B5F35F3B79348274A05E302EE2C /* FIRDataSnapshot.h in Headers */, + 6345F9F23523FC2511CBA173E98C25CD /* FIRDataSnapshot_Private.h in Headers */, + 2494C2411E97FD598D49C668DC6B44D9 /* FIRDependency.h in Headers */, + AE2A4AAA9A98DE08FB34CEBD86E73513 /* FirebaseCoreInternal.h in Headers */, + C3DC1814C54F9047BC3F622CE76EE493 /* FirebaseDatabase-umbrella.h in Headers */, + 84E0CA1241B5287B56CB5E57DC56708B /* FirebaseDatabase.h in Headers */, + A2EB72DBAEA526F00FEC5D50D85CA41B /* FIRErrorCode.h in Headers */, + B94E09C1E2549162E5D7068F3F4767FA /* FIRErrors.h in Headers */, + 8541D6C082F7B93111E7AD288B3B87EF /* FIRHeartbeatInfo.h in Headers */, + 8828DCA475804194FE950AC559A9CB9B /* FIRLibrary.h in Headers */, + 2F7716A1F8D12F701F0C5BB20D8CC314 /* FIRLogger.h in Headers */, + D497442708E5489B523783EAF825686D /* FIRMutableData.h in Headers */, + A2D32D0DF7204674CF2AFB8BEE709C6D /* FIRMutableData_Private.h in Headers */, + A3DD8CF7B61C9BB1CD67B29F521D7195 /* FIRNoopAuthTokenProvider.h in Headers */, + FD4946D8DC99F701B38380F998F6F777 /* FIROptionsInternal.h in Headers */, + 2DA963F6F10C6432AC2836128677E505 /* FIRRetryHelper.h in Headers */, + F3B78D6132C09A006BA59805424A789C /* FIRServerValue.h in Headers */, + 5A49BE780BED21747E5BCB544F217DE7 /* FIRTransactionResult.h in Headers */, + AAB1C6C099525ACA3B9AD0ADDF075EEE /* FIRTransactionResult_Private.h in Headers */, + 702101ECFF609503A6F8701ED8ED700A /* FKeepSyncedEventRegistration.h in Headers */, + 8A26E2B804342A3D00E6FD10D7B5FEF6 /* FKeyIndex.h in Headers */, + 52B867046F638CE4D25775B97F87FA75 /* FLeafNode.h in Headers */, + 00197BF6C4501557C3BC99B81DFAC0FD /* FLevelDBStorageEngine.h in Headers */, + 9980F99E5A1481FBD4FC25BD7220095A /* FLimitedFilter.h in Headers */, + 59F5C0E82357C75D1917ADE67FE8F648 /* FListenComplete.h in Headers */, + A14D2F8BB22E729406AB0BB92447544C /* FListenProvider.h in Headers */, + B3722C8826B36658252E4C72BC9889C6 /* FLLRBEmptyNode.h in Headers */, + C0592DE29AD7F829C8356160EF6E753C /* FLLRBNode.h in Headers */, + DAEA3C69527F4D08C2FC1597D3F0F5F7 /* FLLRBValueNode.h in Headers */, + 0E3FC676750F1FCE239C087EB2E6D8F2 /* FMaxNode.h in Headers */, + A83D12FC092D2F7C2319ABDC8DB44081 /* FMerge.h in Headers */, + 9C87F53FB9DCF372F43E4C582E9CD637 /* FNamedNode.h in Headers */, + 9D5E0F06B552C012EBAB3E6C8E4705DC /* FNextPushId.h in Headers */, + D0625A38CCEB493DD9514C5C3CD858F6 /* FNode.h in Headers */, + 0BF2D63AE4359403053AABC24581FAFD /* FNodeFilter.h in Headers */, + F23DD095353630CBE344B23ADBCAD19E /* FOperation.h in Headers */, + 4B22653EBA41D18BE1096ED6473BCE0E /* FOperationSource.h in Headers */, + E5546DDB0E178716F78C18D720DD82C6 /* FOverwrite.h in Headers */, + E543AF0428A65642BDAEC31855D3F617 /* FParsedUrl.h in Headers */, + F74ACFAD0432A11A50BEBAA87995BB94 /* FPath.h in Headers */, + F065A5C0614E392EE29FCBB2B1948B61 /* FPathIndex.h in Headers */, + 6C0AEF276EA423B89B7E093D861FCE39 /* FPendingPut.h in Headers */, + 2D6BC4E119223FFAAB2C8E4AFC6322D1 /* FPersistenceManager.h in Headers */, + 43CD721013246C189057E90A15D23676 /* FPersistentConnection.h in Headers */, + A7B75B6766CBB8772AFB0734E4012264 /* FPriorityIndex.h in Headers */, + BF507994176A3C34EE789BB992B433F6 /* FPruneForest.h in Headers */, + 9F9A6E681D075EC39272BAE1870FA707 /* FQueryParams.h in Headers */, + CAB775B9C2BC54C3374267A5CA7BC051 /* FQuerySpec.h in Headers */, + 905175ED3B26032DD497D9A0F03E1023 /* FRangedFilter.h in Headers */, + 0F90AFD30D19FA2F88C502EECE262BBF /* FRangeMerge.h in Headers */, + C8F9B76172A394266A64653451388E2A /* FRepo.h in Headers */, + 464EC1E08DCD9058DE9AAB2873F05385 /* FRepo_Private.h in Headers */, + 9579A8B7D3F71DEA7A59AA3729AC6D38 /* FRepoInfo.h in Headers */, + 6242CAEC2F8E2C0BEE8171BDD7624E85 /* FRepoManager.h in Headers */, + C5F616D8FD671D74D087831CFD3DA72B /* FServerValues.h in Headers */, + 07D305CA86236684A8B7DB7A9CF976D5 /* FSnapshotHolder.h in Headers */, + 682F84413FB7860856BDFE2284F3CA5D /* FSnapshotUtilities.h in Headers */, + AC35785AD6ECF42C7DA342AD6613DD0E /* FSparseSnapshotTree.h in Headers */, + 5ED7826DB2ED8CC4DE095524E20ECF86 /* FSRWebSocket.h in Headers */, + 5D1F6D179D2E6DDBCF8CA745F167FAA6 /* FStorageEngine.h in Headers */, + ABEB1A56D2C80F898303252D8CDFDBF7 /* FStringUtilities.h in Headers */, + 67254C5431E7C798A079AC142A3F3978 /* FSyncPoint.h in Headers */, + E7BFAEEA08AD6F53650709C173E285EC /* FSyncTree.h in Headers */, + 6CC40BF6B603E35E518995A1934FF24F /* FTrackedQuery.h in Headers */, + 96948610AAA952B1FBEB7BAC9CED8E9B /* FTrackedQueryManager.h in Headers */, + BC28630AEA12517D2B40A45134C42E78 /* FTransformedEnumerator.h in Headers */, + 918A9A673374AB623CF2307D86C15A4E /* FTree.h in Headers */, + C1DB956F940BD70C4E798C17C81317AA /* FTreeNode.h in Headers */, + C8DAE6E2DD7B93A2FB29F42BFEF482B5 /* FTreeSortedDictionary.h in Headers */, + 46B91B7AAA7B562A8D6F9333B8BB3252 /* FTreeSortedDictionaryEnumerator.h in Headers */, + 8C72E8B429081346274E5A93081D1C80 /* FTupleBoolBlock.h in Headers */, + 201D67C516A0D11EC1DE4AB438669F15 /* FTupleCallbackStatus.h in Headers */, + 051C35E3F0AFBC2B0DFD4BD20953603C /* FTupleFirebase.h in Headers */, + DB80588663B066BDCEDE84ECD2BCF5F4 /* FTupleNodePath.h in Headers */, + FAB11BF4DE580C652061074B84C43827 /* FTupleObjectNode.h in Headers */, + D5271BC47C266B60022061ABDA79E977 /* FTupleObjects.h in Headers */, + 94293FCBF9955603314600B5D7EDC9C6 /* FTupleOnDisconnect.h in Headers */, + 1C6558A6591DAB25C5A28AA82F25091E /* FTuplePathValue.h in Headers */, + 877BD505C3FE6A491E1F517FFDB7F9B0 /* FTupleRemovedQueriesEvents.h in Headers */, + 2C3FD200390564CE0BADB770848ED002 /* FTupleSetIdPath.h in Headers */, + D71485771BF25F5E3F6FD7A50DD21EFF /* FTupleStringNode.h in Headers */, + 5F4C28625699791344FBFC6808A9BDE8 /* FTupleTransaction.h in Headers */, + 8C9F134C7326A6EA58E8F19A477B06FA /* FTupleTSN.h in Headers */, + 7A08D3E6A57D1770548899295DA8D974 /* FTupleUserCallback.h in Headers */, + DBEB33230CB517C515DB56798A8C9231 /* FTypedefs.h in Headers */, + 70978C3161999C402AC8ABD8DADF720A /* FTypedefs_Private.h in Headers */, + 20399816554993CB9A054CB009CC89A1 /* FUtilities.h in Headers */, + 8416D140B256BD069CB602D6204A3850 /* FValidation.h in Headers */, + C67CDF58259FE270848654F0BBB62D7A /* FValueEventRegistration.h in Headers */, + C97EA22722198678BB6118A5A2B6417E /* FValueIndex.h in Headers */, + 4058ABDF86E73027AD91B36D1E0F4326 /* FView.h in Headers */, + C5865C2AB34F73318EA74F04C54FC85C /* FViewCache.h in Headers */, + 6F75FA17DEFB5467875B879FD6EE565D /* FViewProcessor.h in Headers */, + 0DFCF05C003440CA970EB17DD6C48806 /* FViewProcessorResult.h in Headers */, + CC19FB26013C3F6D3D32F7676D1DC84A /* FWebSocketConnection.h in Headers */, + DA64FFAE7EC53366D2CA6B3BA8B81C86 /* FWriteRecord.h in Headers */, + 750B820E8FB644D1C6C858F716DF0D94 /* FWriteTree.h in Headers */, + 3052C53782510E1E0DE4AAA8C5EBE157 /* FWriteTreeRef.h in Headers */, + D14BEE9AC94984CAA75B85F9002039DD /* NSData+SRB64Additions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D7C938E2C29CB71DE27DA06BF9705D0F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 292C7B04F5267FA8DB3DEFEF15478A6C /* FIRActionCodeSettings.h in Headers */, + 64D095CF8F5478D78FD4DEBED5A308F1 /* FIRAdditionalUserInfo.h in Headers */, + 164984C1769476DC3C01516D23ED4AEB /* FIRAdditionalUserInfo_Internal.h in Headers */, + 38367D3DC04822D1C105141FA957CBB9 /* FIRAppInternal.h in Headers */, + 704250AF1BC03587E0B7EC6DEFD83408 /* FIRAuth.h in Headers */, + 7F7C4D96D09CD3201C620DF6E65110BD /* FIRAuth_Internal.h in Headers */, + 2B535018D357A3B2B56AB7073551F9C4 /* FIRAuthAPNSToken.h in Headers */, + F9301E64322318149AC4F02E75E9DA35 /* FIRAuthAPNSTokenManager.h in Headers */, + 423B4495E135FE5C0ED0B4071E8BE0B5 /* FIRAuthAPNSTokenType.h in Headers */, + 7395D8250077260C4CBA38A6C71FB221 /* FIRAuthAppCredential.h in Headers */, + 351C3BD4DEB2E7F2EFAB7D826D7EE53E /* FIRAuthAppCredentialManager.h in Headers */, + F61B0540638CF3C0CF02D667825D3CFE /* FIRAuthBackend+MultiFactor.h in Headers */, + 661A9FABF43DBB4D57FD56A5F200D595 /* FIRAuthBackend.h in Headers */, + CD064F8796CA71F2E8E35786094917E4 /* FIRAuthCredential.h in Headers */, + 20C8FD2B3651B68D732BB7CA4591E51D /* FIRAuthCredential_Internal.h in Headers */, + FEBD9425BB41A3E32676155E656EE13B /* FIRAuthDataResult.h in Headers */, + 300DB9EDB10A0681E9D0F77015D7EB8C /* FIRAuthDataResult_Internal.h in Headers */, + 2033ABD8D11A8F188CB1D5A7C28B8C9C /* FIRAuthDefaultUIDelegate.h in Headers */, + 92D6E7F5BC8F1AC4CD1FAEA20EE8BABB /* FIRAuthDispatcher.h in Headers */, + BC6076CC2D9A8B33AF0B4558B31FC616 /* FIRAuthErrors.h in Headers */, + 1E4AE3B73C726FDA0246496E600A5BC5 /* FIRAuthErrorUtils.h in Headers */, + FB41EE932A129AF4060E44B7859B1F06 /* FIRAuthExceptionUtils.h in Headers */, + 8E16D3EDB94720C597F6CD586EB5F447 /* FIRAuthGlobalWorkQueue.h in Headers */, + 55F2731B30483A892593B5CE9A6E133E /* FIRAuthInternalErrors.h in Headers */, + F04ADA229C116F08A9AE74C7AA90188C /* FIRAuthInterop.h in Headers */, + 15F5C8C87F63A3D89CA54F07930CF0BB /* FIRAuthKeychainServices.h in Headers */, + 3F8EA09FE4E8A77F350D2975EA85234C /* FIRAuthNotificationManager.h in Headers */, + 675438E67A29A8C44DACDCCB3068394D /* FIRAuthOperationType.h in Headers */, + C6183ED0C750FF37035A050E3305B9E8 /* FIRAuthProto.h in Headers */, + C2FBDF0C76469142C9795BD98B0DCBF9 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.h in Headers */, + E6EF4479961ACABE1220DA2BAB584C67 /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.h in Headers */, + 6DAEE1BB6C23773E0DE8D248A93D826A /* FIRAuthProtoMFAEnrollment.h in Headers */, + CBB680E6A640B03ABF43740C90CFA7DB /* FIRAuthProtoStartMFAPhoneRequestInfo.h in Headers */, + 835909BCD28432E37FB3C537EFA3DF2D /* FIRAuthProtoStartMFAPhoneResponseInfo.h in Headers */, + B5669EE2BFAA822E4C2EF780AA370418 /* FIRAuthRequestConfiguration.h in Headers */, + DA5BB3CB6F30F8382EB6BE0797060DA6 /* FIRAuthRPCRequest.h in Headers */, + 98931CDBC0DC65B5EFAC2EF6E6B8DB6A /* FIRAuthRPCResponse.h in Headers */, + 1F7474582F6339605964C52104366D3B /* FIRAuthSerialTaskQueue.h in Headers */, + 96C1959138BDE575761A2EC940E121D5 /* FIRAuthSettings.h in Headers */, + 0B9EFEF5F16CC638C800D057AE1B46AE /* FIRAuthStoredUserManager.h in Headers */, + 0BB7F3F84BFBD9CF5163A448BA3F76C7 /* FIRAuthTokenResult.h in Headers */, + E437D1AD71F866D6F132DE2D7C76106C /* FIRAuthTokenResult_Internal.h in Headers */, + 5E4F12FEAFBCF393F56C65655787D7D0 /* FIRAuthUIDelegate.h in Headers */, + 185224D6AC8CBA6755BFF836EF98AD1E /* FIRAuthURLPresenter.h in Headers */, + B3B077E290BC952DA42B5640CA5DE204 /* FIRAuthUserDefaults.h in Headers */, + 1B584D4EA6BA6603F3B982BDCD7DF8C5 /* FIRAuthWebUtils.h in Headers */, + 2744CB0BA0D82371665CFCE6BA1EE3E6 /* FIRAuthWebView.h in Headers */, + 9FE39550C663547E3DCC144015F56F9C /* FIRAuthWebViewController.h in Headers */, + 03AACEA13BDE64E5A5B1E7B73CB7A91A /* FIRComponent.h in Headers */, + E5D8C8EEDD4793627F5DB60138E9661D /* FIRComponentContainer.h in Headers */, + 982284C4C90F3A37CB1CEB0D81F6952A /* FIRComponentType.h in Headers */, + 29A45C0793FF0DB228A22EFD5ABC91DF /* FIRCoreDiagnosticsConnector.h in Headers */, + 56308A63BDFDBE75095A40BA349AF437 /* FIRCreateAuthURIRequest.h in Headers */, + C2FF1623A2AD96DD41AD38723AF3BBA6 /* FIRCreateAuthURIResponse.h in Headers */, + 764E0FA79B2BBF1DF354D625FF25587A /* FIRDeleteAccountRequest.h in Headers */, + 0ECA3281C3E76B71D71D1EE9395293AF /* FIRDeleteAccountResponse.h in Headers */, + A129DBC6CF1F6675405940C7D5BECBAF /* FIRDependency.h in Headers */, + 87DE0FCA6D20400F43E491E55C7AED1C /* FirebaseAuth-umbrella.h in Headers */, + 6E7F9E6163F85ACCA9353B5573B1A9CD /* FirebaseAuth.h in Headers */, + 3C9648C34F26FBD8B635A0D3A185F779 /* FirebaseAuthVersion.h in Headers */, + 0F32EAB908DFC8FDE2D3B714A40953AE /* FirebaseCoreInternal.h in Headers */, + 0D0C12C3AD18431E78E060F6179AA9C8 /* FIREmailAuthProvider.h in Headers */, + F3AFF6F8C7638836D6B8F5FA0FEFFB5C /* FIREmailLinkSignInRequest.h in Headers */, + 0EE0173B606FDC763F1A14EBCEBB0033 /* FIREmailLinkSignInResponse.h in Headers */, + 1D7F88A99C8741A43BC0CF686E43F0B0 /* FIREmailPasswordAuthCredential.h in Headers */, + 7BEECC8EA66D8C0860DC8138AF2693B0 /* FIRErrorCode.h in Headers */, + 6E07C8DFE37BA80FD964E87D12C64358 /* FIRErrors.h in Headers */, + 1702515A00A41042474A777753CE700E /* FIRFacebookAuthCredential.h in Headers */, + 2F6FEC24220A3DF1B9E2C338B230E3CA /* FIRFacebookAuthProvider.h in Headers */, + 9C3C82D4DE315C4106CAC14F3F23D633 /* FIRFederatedAuthProvider.h in Headers */, + 29EED2DDE45BA8626688A3CDA5ED9D00 /* FIRFinalizeMFAEnrollmentRequest.h in Headers */, + D934648E3E76E7B84B8DCD0CAFA8AE30 /* FIRFinalizeMFAEnrollmentResponse.h in Headers */, + 3E0721C5FA7BB41B555DEFF6B63C784F /* FIRFinalizeMFASignInRequest.h in Headers */, + E7BE6F8A2635F39A83DA391D1ED69423 /* FIRFinalizeMFASignInResponse.h in Headers */, + 53D54F6DFDACF1214F2B604B28CCDE06 /* FIRGameCenterAuthCredential.h in Headers */, + A86AE2F5654920CE67861263686F1B62 /* FIRGameCenterAuthProvider.h in Headers */, + 04E1AA6153D8E934692804A01982FB01 /* FIRGetAccountInfoRequest.h in Headers */, + 359FBAD9D5DA5BECE0F296EFA2E8E765 /* FIRGetAccountInfoResponse.h in Headers */, + BA6E31A35A91951C7F2CDAB31D5E228F /* FIRGetOOBConfirmationCodeRequest.h in Headers */, + C5935896621D6F05F9FD8E9DF0C87D5D /* FIRGetOOBConfirmationCodeResponse.h in Headers */, + 3F59B34B610EAA5F1DCC24E8825BA167 /* FIRGetProjectConfigRequest.h in Headers */, + 30B7536B8896811D74F87E59609BC1DB /* FIRGetProjectConfigResponse.h in Headers */, + FBF11439D89D4AE4C4E7B22E4CDE2BA0 /* FIRGitHubAuthCredential.h in Headers */, + 1F5DDD087484ABCEE446AECCB63EE7B2 /* FIRGitHubAuthProvider.h in Headers */, + A79384496D746E00B4F32F04CB1AD13A /* FIRGoogleAuthCredential.h in Headers */, + 62EE53917282ACE3FCA59F74D29416E4 /* FIRGoogleAuthProvider.h in Headers */, + 422A451F139979443688BD7BE6511256 /* FIRHeartbeatInfo.h in Headers */, + F608A36D494BD46091B61DA00A07B33A /* FIRIdentityToolkitRequest.h in Headers */, + 0F55EFE4975D747D5AD40940BC84C5F9 /* FIRLibrary.h in Headers */, + 46FB6ECDDDE2D572789A81EA97B1DD42 /* FIRLogger.h in Headers */, + C93A44CBAB00C3210C4E6DB9AC0B3BD8 /* FIRMultiFactor+Internal.h in Headers */, + A23EA146EFC5EC2BDADEBF20192A9D10 /* FIRMultiFactor.h in Headers */, + F608C27330385270AB820E4A6FBEDE06 /* FIRMultiFactorAssertion+Internal.h in Headers */, + 1BFEB4DCECE73B7242A3D7797C26F084 /* FIRMultiFactorAssertion.h in Headers */, + 831019A506E1CFE8A7BDA4712278555F /* FIRMultiFactorInfo+Internal.h in Headers */, + D5943A24A39C872D8DB5EA95314936FE /* FIRMultiFactorInfo.h in Headers */, + B24CD4EC9A25599C0921961C39208C3A /* FIRMultiFactorResolver+Internal.h in Headers */, + E369EC0FBFCF48A9423F2564B29EF001 /* FIRMultiFactorResolver.h in Headers */, + FCE66C0F139268FE64F586494A2F3357 /* FIRMultiFactorSession+Internal.h in Headers */, + 6B804CAA8F736BFF23D62A9E41822E58 /* FIRMultiFactorSession.h in Headers */, + 4185C11FFE1B63D2FF34FB7B53674C84 /* FIROAuthCredential.h in Headers */, + 85248DFD6E24F10D401BBB6280DCDF80 /* FIROAuthCredential_Internal.h in Headers */, + B76123BD5E999929EEBED5F55EE66D85 /* FIROAuthProvider.h in Headers */, + FD25233B55493383D6C576E1CEE7E2E7 /* FIROptionsInternal.h in Headers */, + EE22548769A238F68DCE0A8F540C5F61 /* FIRPhoneAuthCredential.h in Headers */, + 8812C6832F78356760DE0923F0208766 /* FIRPhoneAuthCredential_Internal.h in Headers */, + 470345F04DB08B636AACE884401CC35F /* FIRPhoneAuthProvider.h in Headers */, + 5C58345D7984850A8580C632746ACD99 /* FIRPhoneMultiFactorAssertion+Internal.h in Headers */, + 9F0740CAA50D4D3EC7AC59B9DAD6CDD6 /* FIRPhoneMultiFactorAssertion.h in Headers */, + DCA24C8C646B26DEE228BCC7F3B19BC1 /* FIRPhoneMultiFactorGenerator.h in Headers */, + 426BC23107C5F23894ECBE1D47329FC0 /* FIRPhoneMultiFactorInfo+Internal.h in Headers */, + 45A8AAAB778CA6885AD806CBB0B5929F /* FIRPhoneMultiFactorInfo.h in Headers */, + C979A1A2ABF7694CD428642DA16BFB49 /* FIRResetPasswordRequest.h in Headers */, + F81A555804B10264F17B159F83D45E04 /* FIRResetPasswordResponse.h in Headers */, + 8C516A66D945CA04F9A532E68199C050 /* FIRSecureTokenRequest.h in Headers */, + 74041B150381C862CFE3B7A05F7026EB /* FIRSecureTokenResponse.h in Headers */, + C052D4F57373AC725E724B316925EEA6 /* FIRSecureTokenService.h in Headers */, + F94EDC42FB4C8B5B2EE74BB586A6AFC3 /* FIRSendVerificationCodeRequest.h in Headers */, + A453998DE677225FC20FE5E601C7D596 /* FIRSendVerificationCodeResponse.h in Headers */, + AE1B61B2CBC39BFFA0F17E60CC012A25 /* FIRSetAccountInfoRequest.h in Headers */, + DB446AF711F320FC5D625B70E233071E /* FIRSetAccountInfoResponse.h in Headers */, + 09AD282B1DD0537B45C2B752EBF5B09B /* FIRSignInWithGameCenterRequest.h in Headers */, + 6CC2C80D1CEB68F1B21A99AC2ECA6386 /* FIRSignInWithGameCenterResponse.h in Headers */, + 988DE22FF9CE401D0D17643FFA04FE35 /* FIRSignUpNewUserRequest.h in Headers */, + 687FA8E493C93E1802D575740872F443 /* FIRSignUpNewUserResponse.h in Headers */, + 453AE47A48F9C3F188D8209C0B0A6772 /* FIRStartMFAEnrollmentRequest.h in Headers */, + C2AD48867D557C2872A51ADD54507FC1 /* FIRStartMFAEnrollmentResponse.h in Headers */, + 3FA835A1652626C3FB69DFD515DF1A67 /* FIRStartMFASignInRequest.h in Headers */, + 2C16297567B94FAD20B696F0BA055C42 /* FIRStartMFASignInResponse.h in Headers */, + 103EE4551AC02CF6FB95F308BFA33FD6 /* FIRTwitterAuthCredential.h in Headers */, + E3C8164AB15FD3E49F9596AB0D0B864E /* FIRTwitterAuthProvider.h in Headers */, + EB95AAE8ED1D72BAD0B6FF407F09C5AC /* FIRUser.h in Headers */, + 5D34DA34E00D1CE5B2BC83FE04DB0037 /* FIRUser_Internal.h in Headers */, + A1899D60120878FAAC7E9A0E1B3E38E7 /* FIRUserInfo.h in Headers */, + 92DB87D1751441DBCC224CF43AF2DEB6 /* FIRUserInfoImpl.h in Headers */, + 568235CAF30B5BBFDF4E7A6D18C70517 /* FIRUserMetadata.h in Headers */, + 20D706725AB113719E24B9D3D1A85956 /* FIRUserMetadata_Internal.h in Headers */, + 3E2B62DD286BFD7ED1A58BA440849967 /* FIRVerifyAssertionRequest.h in Headers */, + 2C9085862E0C3305B61C73875F4224A0 /* FIRVerifyAssertionResponse.h in Headers */, + 03AC71BC9F79E188BC0E854CAE4F73DE /* FIRVerifyClientRequest.h in Headers */, + 7C1811FD8E7629E7D45AD8F41E699810 /* FIRVerifyClientResponse.h in Headers */, + 736F02A4A427A481427A3C8465EBB3AF /* FIRVerifyCustomTokenRequest.h in Headers */, + 88BB134FCEB53925A505A58C1474B276 /* FIRVerifyCustomTokenResponse.h in Headers */, + 2F95401E0DA397E88652888DB14DAF59 /* FIRVerifyPasswordRequest.h in Headers */, + 5852D1793638B975393CF5B6D6C21B52 /* FIRVerifyPasswordResponse.h in Headers */, + 9A6C9C790751416F068BD56C103E536B /* FIRVerifyPhoneNumberRequest.h in Headers */, + EBBF6C1E5FA3828EB3EAF8F6F2E1FFB0 /* FIRVerifyPhoneNumberResponse.h in Headers */, + 22ABD8DF323AB3AC8E4D33D1B15052EE /* FIRWithdrawMFARequest.h in Headers */, + 85B5CF9BA2ABD15512ED5E2FBC1773C2 /* FIRWithdrawMFAResponse.h in Headers */, + 09368BC6AE4BB0DD312FFE6C47FAD4D7 /* NSData+FIRBase64.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */ = { + isa = PBXNativeTarget; + buildConfigurationList = E89811131BF8158FC162B131E90D320F /* Build configuration list for PBXNativeTarget "FirebaseStorage" */; + buildPhases = ( + 10CE1F5C0EBB29B2200FC8A8DA5957CF /* Headers */, + 216E9F569F209C864E5C79551608D01D /* Sources */, + 771934A8292F9E56AF16AD9C444EFBBE /* Frameworks */, + 86A43E71108716C57D7B00D68CE02148 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C16CA301A08D3A7F79032732793C3D2D /* PBXTargetDependency */, + 27FD3D09FA099C1583365C9BE90948A2 /* PBXTargetDependency */, + ); + name = FirebaseStorage; + productName = FirebaseStorage; + productReference = 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */; + productType = "com.apple.product-type.framework"; + }; + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9B149B704151435145561397AF0830FB /* Build configuration list for PBXNativeTarget "PromisesObjC" */; + buildPhases = ( + 29A628FE701AF8BAC1D0D5211E5A09DB /* Headers */, + A0C1BAEE747133B982DB482F7E4987EE /* Copy . Private Headers */, + 405382FE2AA5F751FF32CABE0F41BE63 /* Copy . Public Headers */, + A11F074FF69E309DAD7629265FA1E9DC /* Sources */, + 2A50BBBB67ED88BFDFCF280534A2E913 /* Frameworks */, + 55778EA3E1560F0E6EA6B7A9E8FFE6A3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PromisesObjC; + productName = PromisesObjC; + productReference = 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */; + productType = "com.apple.product-type.framework"; + }; + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8730A7F30233C13704CF5AB33818D02 /* Build configuration list for PBXNativeTarget "FirebaseCore" */; + buildPhases = ( + 25BAD54C6901DD7866C33A44CAAE3BC7 /* Headers */, + AD75762EB133332099B72E3CC6C667EB /* Sources */, + 8527AD5C6F1EE04394A63A6D7529F155 /* Frameworks */, + 780D545634019FCC071AB83B16230352 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5AFFF32F01F2F37D9F46F79164076DC7 /* PBXTargetDependency */, + 9129CC909DCF71C59C68BD1E6F3DC1C2 /* PBXTargetDependency */, + ); + name = FirebaseCore; + productName = FirebaseCore; + productReference = E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 4F91D2ECAC31D494531E121B750D88A5 /* FirebaseUI-FirebaseAuthUI */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9C565F1E674279068C73FA1B08B45E02 /* Build configuration list for PBXNativeTarget "FirebaseUI-FirebaseAuthUI" */; + buildPhases = ( + 7E965BC49E36BE45CB918BF70F426071 /* Sources */, + 307F3A574328AD48FA2EC0FEAF73B536 /* Frameworks */, + 01DB9712AEFC1B44C5CF9875DF93BCCD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "FirebaseUI-FirebaseAuthUI"; + productName = "FirebaseUI-FirebaseAuthUI"; + productReference = A3BA8163828042C7132F40FBC25E24D5 /* FirebaseAuthUI.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */ = { + isa = PBXNativeTarget; + buildConfigurationList = 71F82A6135D33FBB3D18A38AFFE08885 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */; + buildPhases = ( + 1057C3C3EFB3A71D0F404924ED9638CE /* Headers */, + 034101E3F158775B3C4AD99E0745EF94 /* Sources */, + 288EB6573D0226789F0BDCD82D886C6F /* Frameworks */, + E19A058AB7F7DBDC5EE5893E774F04EC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleDataTransport; + productName = GoogleDataTransport; + productReference = 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */; + productType = "com.apple.product-type.framework"; + }; + 5C642AA10FB29936669CC269F42079C6 /* AppAuth */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9FB8D339D52B52F9DAB7BA9CD4DC84FF /* Build configuration list for PBXNativeTarget "AppAuth" */; + buildPhases = ( + BF20DD677E68B0FFF096FA87BA4F642E /* Headers */, + FA40C5373E6F05613AE4464C1A8C3500 /* Sources */, + 16CF22217BEA907AC6550A5C485822F1 /* Frameworks */, + 789D540271448693859C5D41E90A58D6 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AppAuth; + productName = AppAuth; + productReference = 3FD1B4C1246D643E9476438C28048FA8 /* AppAuth.framework */; + productType = "com.apple.product-type.framework"; + }; + 6051175E4E4C37209FBE2BF5BE4627BD /* FirebaseUI-FirebaseGoogleAuthUI */ = { + isa = PBXNativeTarget; + buildConfigurationList = 35458B72DBE937B906DFEB68EB76D03A /* Build configuration list for PBXNativeTarget "FirebaseUI-FirebaseGoogleAuthUI" */; + buildPhases = ( + 9CBA368F8324E647D43B9E41D7B5DC40 /* Sources */, + C4750097903995BD1C45CD8DEA358160 /* Frameworks */, + BDF537E623E8658A8AEC717E6FCB0565 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "FirebaseUI-FirebaseGoogleAuthUI"; + productName = "FirebaseUI-FirebaseGoogleAuthUI"; + productReference = CE49BDFC8463EC230FD4E8C9B3385281 /* FirebaseGoogleAuthUI.bundle */; + productType = "com.apple.product-type.bundle"; + }; + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */ = { + isa = PBXNativeTarget; + buildConfigurationList = 50EC3E189DDE4DF2306F3A862792E1FF /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */; + buildPhases = ( + B5FCC80568D8E29D856A0FB46A4100F9 /* Headers */, + BFD7F1EF6AF863993F65404FF6ABD505 /* Sources */, + 9AABEF3517D06D364480F0EAD6AA38FB /* Frameworks */, + BB4E6CA19D5373C3403122A05B37D838 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 722C50D47EE62F1F1D11E9D3AABB3427 /* PBXTargetDependency */, + 1CC9595BE02776E2952547CCF0D05ED2 /* PBXTargetDependency */, + C76C2A7BB91DEE6AB780A019BCEB847D /* PBXTargetDependency */, + ); + name = FirebaseCoreDiagnostics; + productName = FirebaseCoreDiagnostics; + productReference = 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */; + productType = "com.apple.product-type.framework"; + }; + 6AE4A3D573DED275B034E20506596C62 /* FirebaseAuth */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5AC7D7BAAD2889D785E1B07169E4911C /* Build configuration list for PBXNativeTarget "FirebaseAuth" */; + buildPhases = ( + D7C938E2C29CB71DE27DA06BF9705D0F /* Headers */, + C84B0BF180D12428F8DB0E8555D2D5CE /* Sources */, + 6BF3AD3CA039D7802D2E3C66001461A3 /* Frameworks */, + 0C5652D42CABB690D7F4A1374976249E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 058CDD771575B7F2702CD70417C4FA33 /* PBXTargetDependency */, + F00E3216A1D9517824DC84147D1B48A9 /* PBXTargetDependency */, + 11482A16E2499B32E1F9E8942C504A82 /* PBXTargetDependency */, + ); + name = FirebaseAuth; + productName = FirebaseAuth; + productReference = 43B1E4CD7B30B9FD278100133C2AC788 /* FirebaseAuth.framework */; + productType = "com.apple.product-type.framework"; + }; + 6D45934038562DBC96227173D041A9C1 /* FirebaseUI */ = { + isa = PBXNativeTarget; + buildConfigurationList = DF9B026542CE18E68EB08595D6AF5A04 /* Build configuration list for PBXNativeTarget "FirebaseUI" */; + buildPhases = ( + 469827005540582C6EB83E949481AA5D /* Headers */, + 4ABEF850A92F153770B2277DA98E3037 /* Sources */, + C07D9F3989267B68F049F291CF9288C5 /* Frameworks */, + 9CC0C19593B71B717892C9ABA65C3071 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F18A38D42B84652687C39B25FA2E74E1 /* PBXTargetDependency */, + 55EC04FEDD874A1939C5BE4BF5F0D4C1 /* PBXTargetDependency */, + 80AA0396EB3E3860BD6F20227D329362 /* PBXTargetDependency */, + 242C2BEED77BDC312A3E12D2B887AEDA /* PBXTargetDependency */, + A8DF7E6143B9E581DA6CCE9438DDCE46 /* PBXTargetDependency */, + ); + name = FirebaseUI; + productName = FirebaseUI; + productReference = 62F454249D6AA95C313D27B86A06B4F4 /* FirebaseUI.framework */; + productType = "com.apple.product-type.framework"; + }; + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2562FCEBD94AC96F30940CF976E58B73 /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */; + buildPhases = ( + C0F878EB58A135F908E3E26677366E30 /* Headers */, + 97EDE691559E6479F410936ADD52FFC8 /* Sources */, + AD8BF722AF274344DDFA95F92F76B092 /* Frameworks */, + 3D8170371688F79DF5570F27FCBC6CFC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + B33B63DD38C271F72B168288EDBAFE03 /* PBXTargetDependency */, + 5F2D4959316FC456115F4CC1505E0929 /* PBXTargetDependency */, + ); + name = FirebaseDatabase; + productName = FirebaseDatabase; + productReference = 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */; + productType = "com.apple.product-type.framework"; + }; + 8627999EF1D5E93E13DAFF580DA8CDCF /* GTMAppAuth */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0A2F227A2B6E041D0DE9C55C0A673550 /* Build configuration list for PBXNativeTarget "GTMAppAuth" */; + buildPhases = ( + 12CC7779BFA71300C62FF3D6F904A62C /* Headers */, + D45C550ED36B0C2816AA743B9875AE93 /* Sources */, + E980906BBCCA56251CEB7CC0D2D4C47B /* Frameworks */, + EAC588FC0A476FF71C316002EBD69869 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 598C058565BA97E2F0BC79E21739F980 /* PBXTargetDependency */, + 44ACA436AFF162787B57713C15CE151E /* PBXTargetDependency */, + ); + name = GTMAppAuth; + productName = GTMAppAuth; + productReference = 6FD122EA0AB9AB2A8FFA5F676C795DF0 /* GTMAppAuth.framework */; + productType = "com.apple.product-type.framework"; + }; + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */ = { + isa = PBXNativeTarget; + buildConfigurationList = 399FEFEFD30AFF53045B521C98EB302D /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */; + buildPhases = ( + 4BC2A1E2B8A2FBB214975D3840B7740E /* Headers */, + DD1A38B09272920CB5F3597DE401D6B9 /* Sources */, + A9965926B4060D881F8C257FBF691E4F /* Frameworks */, + EC0897EE556CE45D749AC94E16344755 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + FE620EB6798E24167774587C5BFE2DA8 /* PBXTargetDependency */, + ACE867CE743A04FCEE725CDB1A868026 /* PBXTargetDependency */, + 211FFB9BAE629EBD1FA548E8B6019FC6 /* PBXTargetDependency */, + ); + name = FirebaseInstallations; + productName = FirebaseInstallations; + productReference = 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */; + productType = "com.apple.product-type.framework"; + }; + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9C971348766DBCAE0EB4E87A65E713B9 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */; + buildPhases = ( + 7E758F98F082A7E4050E9F229D1D46B6 /* Headers */, + EE8987EEF880C18D10981FFDD9D8A56F /* Sources */, + 0AFE9A74FD29F7DE5D5FB75D8ADCADD9 /* Frameworks */, + 9BE3A2FDEC319EA8491BBEE6F80CE932 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8D9964CFF970F8122123D5465614395A /* PBXTargetDependency */, + ); + name = GoogleUtilities; + productName = GoogleUtilities; + productReference = B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */; + productType = "com.apple.product-type.framework"; + }; + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3BC9A595AD3BC93490E6CBCB50B2E53F /* Build configuration list for PBXNativeTarget "leveldb-library" */; + buildPhases = ( + 69D968EDF3D8E4D392307035F5EC7024 /* Headers */, + 1A71101EEF5635C6B31774CAF4131C08 /* Sources */, + D10EA948D710666D30B4D6C80EF714F8 /* Frameworks */, + F55F7668E294AAFBC08187CC02D200CB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "leveldb-library"; + productName = "leveldb-library"; + productReference = 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */; + productType = "com.apple.product-type.framework"; + }; + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5BEC0F5D4AB0F843C0076E8C32DEC47E /* Build configuration list for PBXNativeTarget "nanopb" */; + buildPhases = ( + 3E7A59CC470AF47F5D93F514201E5196 /* Headers */, + 3EBD07698E7EFA0E27C200F51980A048 /* Sources */, + 0B65A1B0CBA6A62115EC026D09D52C67 /* Frameworks */, + 4E876C321963EB7D24DC25E93CBCB7C4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = nanopb; + productName = nanopb; + productReference = 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */; + productType = "com.apple.product-type.framework"; + }; + D45A553340EF994A76C7F522300BA5BA /* Pods-MyExperiences */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4AE02767AC39C6230F2DC09DAFB96F5D /* Build configuration list for PBXNativeTarget "Pods-MyExperiences" */; + buildPhases = ( + 63E4537496312DBA8F8E53E40D1E9335 /* Headers */, + FDC5C1A195E2E38C77F9932070CEC8A9 /* Sources */, + 9145DBFE6D975B79CD63546350269025 /* Frameworks */, + CB50A8FF12777DE002FB91501C142567 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6CC16101294855C178FAE376855B1E0C /* PBXTargetDependency */, + 6ACE31262D9464F42FB02A8DF2B4AF26 /* PBXTargetDependency */, + F5214B9E4EEBC5649914D20EC00DC06D /* PBXTargetDependency */, + F62F221BD8BA6C3E17D5C844993E95CB /* PBXTargetDependency */, + 0DF43D9FBFF86CC4E26F38AA656A8CCA /* PBXTargetDependency */, + 80C3C75F2547C59CC1E12F760E0356E6 /* PBXTargetDependency */, + 9B701E31E7E3EA1335E62F6BF220C3CF /* PBXTargetDependency */, + A2A63968F85F1E6F7EDCA30A664A72C7 /* PBXTargetDependency */, + 55F1D58B062056D5BF67D2D266C40E76 /* PBXTargetDependency */, + 729CCCAD8A0BC70FAB53583BF03B29D8 /* PBXTargetDependency */, + 21263CB0995072855461EC88B90EE6C4 /* PBXTargetDependency */, + 1CCB5F9ABA8C28428C910FA4E9466868 /* PBXTargetDependency */, + 1C909B19E05F29CBFA9C74E247EF13D1 /* PBXTargetDependency */, + 90C02305739A6B4287D36F1A6679A248 /* PBXTargetDependency */, + 5A158FB70B0CC76E4EC4B49EC5D083A7 /* PBXTargetDependency */, + BB9DF6DCD7E0A950C7162EC456618B30 /* PBXTargetDependency */, + BDBAE6F51DD6B1FAA6275A31398BA7F6 /* PBXTargetDependency */, + 7FCEDEC03E910C5A23F8A29F72997DE9 /* PBXTargetDependency */, + 78F437B92AD2A3917E852E339CF694A2 /* PBXTargetDependency */, + 2B621894FE08AF8DE575849709762BE1 /* PBXTargetDependency */, + ); + name = "Pods-MyExperiences"; + productName = "Pods-MyExperiences"; + productReference = 25BE0E179757406561E2975B3099D56C /* Pods_MyExperiences.framework */; + productType = "com.apple.product-type.framework"; + }; + D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A3C9ED2226B899F6727A4FA61E98A07 /* Build configuration list for PBXNativeTarget "GTMSessionFetcher" */; + buildPhases = ( + 4493DFB71B788DB8D7B1F9CDF049D4C0 /* Headers */, + 99C8F0F15AC77E5C7537926806AD024D /* Sources */, + EF7F5A1366D52D41CFEE3FF47BCD96E2 /* Frameworks */, + 8060C7B70ECFEA581E3BF947A9EA060D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GTMSessionFetcher; + productName = GTMSessionFetcher; + productReference = C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */; + productType = "com.apple.product-type.framework"; + }; + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8D15AAFED93654EEEA494F14C576182B /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */; + buildPhases = ( + 39E296290881AABF68B18A19700F158A /* Headers */, + A0A099D05B462309479B42964EBFA7D4 /* Sources */, + 82A44DCD4F9E83CF41B5F67761A3A661 /* Frameworks */, + CEEB92D62C275E97C3C31E035EC00D2A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 799FD051C980C75E7031F22B9A3F3E3A /* PBXTargetDependency */, + 37C67F0FC57A90D9601A609C4B3217DB /* PBXTargetDependency */, + ); + name = GoogleDataTransportCCTSupport; + productName = GoogleDataTransportCCTSupport; + productReference = 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 147DB21F2D8647751EAFCF3213D751A5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5C642AA10FB29936669CC269F42079C6 /* AppAuth */, + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */, + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */, + 6AE4A3D573DED275B034E20506596C62 /* FirebaseAuth */, + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */, + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */, + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */, + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */, + 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */, + 6D45934038562DBC96227173D041A9C1 /* FirebaseUI */, + 4F91D2ECAC31D494531E121B750D88A5 /* FirebaseUI-FirebaseAuthUI */, + 6051175E4E4C37209FBE2BF5BE4627BD /* FirebaseUI-FirebaseGoogleAuthUI */, + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */, + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */, + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */, + CAD3534FC55B0333104E5117C0A9A324 /* GoogleSignIn */, + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */, + 8627999EF1D5E93E13DAFF580DA8CDCF /* GTMAppAuth */, + D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */, + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */, + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */, + D45A553340EF994A76C7F522300BA5BA /* Pods-MyExperiences */, + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 01DB9712AEFC1B44C5CF9875DF93BCCD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F5ADDB1B39D7E123C5F905AB86E038F /* ar.lproj in Resources */, + 9DD8C66385374FED4BBEB88CFEE1AA88 /* bg.lproj in Resources */, + 7550AC1065D21D0F055B71D60963A6CB /* bn.lproj in Resources */, + D903BE8C04492B3680081B4D9165C63A /* ca.lproj in Resources */, + BC4CBD3E4A3760B4E2679B261709BCE2 /* cs.lproj in Resources */, + 604950F7EBBE3555711A5B61F54A4269 /* da.lproj in Resources */, + F1872FB4AA315ABD8D17466B5B226722 /* de-AT.lproj in Resources */, + 046BDDC81155DF76DD41278878DD2903 /* de-CH.lproj in Resources */, + F83A172A04A254A7884CC9C004FD0841 /* de.lproj in Resources */, + DE7A77D8981731B141BFDA6941F13A4D /* el.lproj in Resources */, + 6C18E9EE8933E2363D16600DECF70A8D /* en-AU.lproj in Resources */, + 2F7DE274D6D92482FC6B23802733B4EE /* en-CA.lproj in Resources */, + AF4CA8342FD28D7F603651275559EECD /* en-GB.lproj in Resources */, + 125AD7E43E40469ACF1CD61FE87C2C85 /* en-IE.lproj in Resources */, + 9583B3E941D332DACB9506C041F853F2 /* en-IN.lproj in Resources */, + 69EF791CC8EBAAD9AAF671EF3C5C2ACD /* en-SG.lproj in Resources */, + 7E4C3FFB907CB2E01C3F5411EE2D08C6 /* en-ZA.lproj in Resources */, + B8131349639510A9567770D9A89168A0 /* en.lproj in Resources */, + 8218B58842B931482D288F9C179C1C4A /* es-419.lproj in Resources */, + 556349A2E90B66ABA58FF61671CA7ED5 /* es-AR.lproj in Resources */, + 02CCB32F8551290FA005E433C496610E /* es-BO.lproj in Resources */, + CF2CEAFC127BA38E7D6F1AC771BBA3BC /* es-CL.lproj in Resources */, + E8AD283782868B5C6CB7D49A0914F12D /* es-CO.lproj in Resources */, + 7ADDC41744D0F3D3D3F019753E17E80F /* es-CR.lproj in Resources */, + 96A159C5D4849FC963A42269C75234B0 /* es-DO.lproj in Resources */, + 27DAD18D5B0BE098DC0F1B931C045714 /* es-EC.lproj in Resources */, + C099234E569B89298481103E98A64056 /* es-GT.lproj in Resources */, + D0AC059F8F557C30AF3AC65DF729A21C /* es-HN.lproj in Resources */, + E79E1DEEE6343F54BB7C88B388F1BB27 /* es-MX.lproj in Resources */, + AC95C3D0C8204091188F4276314ED68D /* es-NI.lproj in Resources */, + DB72A4C0F3842894EE3485E3B9DEF3CE /* es-PA.lproj in Resources */, + 23243747D4DADC64049721E4351DEC43 /* es-PE.lproj in Resources */, + C8155934825A976568562F6065028BF0 /* es-PR.lproj in Resources */, + 3DA80B564E29D5DB2CEF425EB334E919 /* es-PY.lproj in Resources */, + A31F4044B8F9972C992C68F81DD19605 /* es-SV.lproj in Resources */, + B7B63DC78FF94B33A1D34568261823C1 /* es-US.lproj in Resources */, + 43A17DD94A43D97AB409CED1E7BA186C /* es-UY.lproj in Resources */, + 7489186AFC0AB8169E96232277138495 /* es-VE.lproj in Resources */, + 30834B54C998829A1AC14C31B96F3564 /* es.lproj in Resources */, + C932A62D036F33894100D269A814A809 /* fa.lproj in Resources */, + B8C440235C0D9EF950260FF4E2DFFF55 /* fi.lproj in Resources */, + FA8004E02DFB16E6E4671AED8E96B847 /* fil.lproj in Resources */, + 6BD6462A74CEEC599377E3D62409302D /* fr-CH.lproj in Resources */, + 83F5625E3BBFAFC6F6E1C6EA7A516C6B /* fr.lproj in Resources */, + 26D55996275D5D789D3F6E7DE7AC9202 /* FUIAccountSettingsViewController.xib in Resources */, + 077CE3975A409D2CCB2066EF790A2560 /* FUIAuthPickerViewController.xib in Resources */, + 66D679B90F1CA345F347E6E776B4983E /* FUIAuthTableViewCell.xib in Resources */, + 196CFC01D9D935E653A494A4E29C268B /* FUIInputTableViewCell.xib in Resources */, + 81C45B1D2021093BAA0D8E848822C0BE /* FUIPasswordTableViewCell.xib in Resources */, + 1E6036CD752AD8FA051D55F790802066 /* FUIStaticContentTableViewController.xib in Resources */, + 01322E8416BAA0FBAD9488F437562DA4 /* gsw.lproj in Resources */, + EE8D546D679D2358F8C9F88AD50C92AA /* gu.lproj in Resources */, + 7E655E800382E28747E61BD3DD084D7A /* he.lproj in Resources */, + 6EA78EE3630B21318D3441D1B0D8AB7B /* hi.lproj in Resources */, + 0F837C468B671045AF6922BC1AE34A17 /* hr.lproj in Resources */, + 351FB1285EC73346A4BA5135B8E521B9 /* hu.lproj in Resources */, + 65E794BF0EB93249952535E25AAD7555 /* ic_account_circle.png in Resources */, + 0A293264F3505A12229B2D28EEF9CCF2 /* ic_account_circle2x.png in Resources */, + 258ADA4518173302B8764079C38AED0B /* ic_account_circle3x.png in Resources */, + 8D45E4BEC5930E087E1E2C7D02269107 /* ic_visibility.png in Resources */, + C83383E1E837E12F876C0C8DB2F62683 /* ic_visibility@2x.png in Resources */, + 9FE95AB76727B51B2D8C05A47933AB11 /* ic_visibility@3x.png in Resources */, + 1C4ED94042C78A1CF1B53357D7FC2495 /* ic_visibility_off.png in Resources */, + 91D8EC216364B7084ED12776044A0640 /* ic_visibility_off@2x.png in Resources */, + 0FCB629DA14579BACECA832EAF9B659B /* ic_visibility_off@3x.png in Resources */, + F5E16190B9673C1FFCD855ECF2D53F6E /* id.lproj in Resources */, + 6AAFBCBD61515508338F589D69E75603 /* it.lproj in Resources */, + A71642B53A475EE9AE493557F253A095 /* ja.lproj in Resources */, + CBAC799C647E901E8584AC832E9C9B95 /* kn.lproj in Resources */, + DBBE4B8E6203C75F1169240E0D3CB058 /* ko.lproj in Resources */, + B5AD23C44AB0C2D067FB433629BA13DA /* ln.lproj in Resources */, + 86634D0E28C70C490B41AD0A80F708D6 /* lt.lproj in Resources */, + 11EA9C12F47BE1E080C68147850FBF65 /* lv.lproj in Resources */, + 09BA60872EA3FB0F04659071ED913C62 /* mr.lproj in Resources */, + 3DEC7494C09A62FE6B75E0B4AD0AA5F8 /* ms.lproj in Resources */, + D5BB5726B3BF325BB43EB66FB9B682BE /* nb.lproj in Resources */, + 6EACA84AA4C94A8969D1A7F8A9FF7E06 /* nl.lproj in Resources */, + 969CD84081A1685FA766D54A2206858D /* nn-NO.lproj in Resources */, + D6CBB208F35FE6BFFCCE18FD6DD36F28 /* pl.lproj in Resources */, + E78B4185E629DF134AA7A3B601181F03 /* pt-BR.lproj in Resources */, + 24EA386C593881D57578C9EA5233D90E /* pt-PT.lproj in Resources */, + A1FD06AEB073D6E84F7629C7C2BC2833 /* pt.lproj in Resources */, + 83AAF2332D14B045119D1243039D97AE /* ro.lproj in Resources */, + 1A433A2C2D1A8EE0107949AAC343B9DF /* ru.lproj in Resources */, + 1B9467E56F5AC87A6DC43329E42DE40A /* sk.lproj in Resources */, + E57C46D80106AD4F7D13F5DF94918E36 /* sl.lproj in Resources */, + 91C0BA0E9F54FE577AF208622F2482AC /* sr-Latn.lproj in Resources */, + 03ABC297C208C94A6AC41284AA1A6931 /* sr.lproj in Resources */, + F19EF42A235378A4B64C0690CCB7EDA7 /* sv.lproj in Resources */, + FAB763CD2C3F810473A37FBAE38A7778 /* ta.lproj in Resources */, + 5757C63ACB8CAE9CF3A315D64F51299F /* th.lproj in Resources */, + 710C7C342D9B884A57B31554A8301D3A /* tr.lproj in Resources */, + D52132175ECC09152FD6B624A676EF49 /* uk.lproj in Resources */, + AED5EB92C1BBDB0227A8C83E6F839542 /* ur.lproj in Resources */, + 08B1AA1DA2B95D9ABEB2E5E7F756BCBF /* vi.lproj in Resources */, + 6BAC35A35D56780297767C0649A0D9C2 /* zh-Hans.lproj in Resources */, + 39DE7A791BCDC4D4801C252870521687 /* zh-Hant-TW.lproj in Resources */, + B2DB7D77CDAF01320311D54A6C2B6A18 /* zh-Hant.lproj in Resources */, + 7B44B7901BDF3803A6C25612D5EC5901 /* zh.lproj in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0C5652D42CABB690D7F4A1374976249E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D8170371688F79DF5570F27FCBC6CFC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4E876C321963EB7D24DC25E93CBCB7C4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 55778EA3E1560F0E6EA6B7A9E8FFE6A3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 780D545634019FCC071AB83B16230352 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 789D540271448693859C5D41E90A58D6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8060C7B70ECFEA581E3BF947A9EA060D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86A43E71108716C57D7B00D68CE02148 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9BE3A2FDEC319EA8491BBEE6F80CE932 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9CC0C19593B71B717892C9ABA65C3071 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BB4E6CA19D5373C3403122A05B37D838 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BDF537E623E8658A8AEC717E6FCB0565 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A57DB5709355A7460C93C161EF8B8971 /* ar.lproj in Resources */, + 1AA52F54BD216582909D04A084F42C1B /* bg.lproj in Resources */, + 4A619B3454E7EF3C9E3712D438196E85 /* bn.lproj in Resources */, + 1EFC1611BD2CE88883B5E2AC40C2EF79 /* ca.lproj in Resources */, + D619BB0AFDF07B688B5F1EC9D28CBFED /* cs.lproj in Resources */, + CC1E613809D4F1DEA773CB2CFF7E7E7B /* da.lproj in Resources */, + 0A76A49CAD54FC8D7B15344AD19A3CF4 /* de-AT.lproj in Resources */, + 5E6454BE594C67BDB528E18B85C62801 /* de-CH.lproj in Resources */, + 896E8737F32EA9E5D369123FA6300C49 /* de.lproj in Resources */, + 41CE7886546CDEE018D896EC2B8120BF /* el.lproj in Resources */, + 00DEDBFB7AC7FD5602601B725215FBC4 /* en-AU.lproj in Resources */, + 794A28D942D682A8EB90588F63F3709D /* en-CA.lproj in Resources */, + 50A22F3F84F6220DB2664EDBDF67AF3F /* en-GB.lproj in Resources */, + 8CFFE7B6F1A89899F45DD6416CA03F40 /* en-IE.lproj in Resources */, + 8093597DAF1956ED29ACB550847FBCF4 /* en-IN.lproj in Resources */, + 0EE4A6689AA07EA982A2957C64FA95F9 /* en-SG.lproj in Resources */, + E0454BD85399837BAB438DABB3F6E60C /* en-ZA.lproj in Resources */, + DD25EFCEAD905565F239CB758E249371 /* en.lproj in Resources */, + 7FB2D7E84CB375FE19E2503809D8DE30 /* es-419.lproj in Resources */, + 92B5409B65A42C3D778CC4F6B5AE408A /* es-AR.lproj in Resources */, + 761AB4CEB901338477D75C8B9177B5DF /* es-BO.lproj in Resources */, + 59731CB6F46FF7F63F6A400542C8FCB1 /* es-CL.lproj in Resources */, + A9FF7C8B78F63CAD990E872F352B5F08 /* es-CO.lproj in Resources */, + 5248ACF7F7182E21D852B2730B3ED205 /* es-CR.lproj in Resources */, + 648DB2FD4628E41C81C4D2CCE0C47202 /* es-DO.lproj in Resources */, + 76282547D1A0FCBB793D803F330BCCF1 /* es-EC.lproj in Resources */, + 731319FF83413B389A0C20B2EC7CD6DA /* es-GT.lproj in Resources */, + 571E78F80A43E8011456893D29F36D15 /* es-HN.lproj in Resources */, + 63C9EAD131C3189391781DFAE115283F /* es-MX.lproj in Resources */, + 1080C7CBAF82E3C295D3F7EBA0CC6A92 /* es-NI.lproj in Resources */, + C0988DCAEF52C0A605F758B0688C00E5 /* es-PA.lproj in Resources */, + B52BB6202539D138732BC2F2521A00BC /* es-PE.lproj in Resources */, + C4E0987FD50FEE7737967B8D83201220 /* es-PR.lproj in Resources */, + D4E2151D071B68DC675553D730F67D81 /* es-PY.lproj in Resources */, + 64E4272B0D45B5F9815226F5E10394D0 /* es-SV.lproj in Resources */, + ADCF1FB700F702053293F3BA943084AF /* es-US.lproj in Resources */, + B531FEE2F1C9E74B73647EC98DD0ECE6 /* es-UY.lproj in Resources */, + B37E968F9A7B713E9D6DA6C95AF8F073 /* es-VE.lproj in Resources */, + 1FAE22850E5DFA7BCCA885C8C5FB73BC /* es.lproj in Resources */, + 69EAB586BDAEE273C8BE3D2290CEFF9D /* fa.lproj in Resources */, + 43EF2CA6A6E51F8A6C883103DD9612BF /* fi.lproj in Resources */, + D27E7F9CEA4834A3C5CD122F3DFCAEF4 /* fil.lproj in Resources */, + 4D603A0713102211BB0DACD4C78A1AA1 /* fr-CH.lproj in Resources */, + A964875BA642838FD01FDFF53E5C6E20 /* fr.lproj in Resources */, + 17FEFA87927228952E256731494E9ACD /* gsw.lproj in Resources */, + F9940A407864D41F952E05184B227F67 /* gu.lproj in Resources */, + 4EF38065E0F4C054D7D005F503EFB2A7 /* he.lproj in Resources */, + 397978A03CC7F1E8F1F0109235EED82C /* hi.lproj in Resources */, + F47356F17DCDEB91F60B6E75D5767AAF /* hr.lproj in Resources */, + CEC0F9D226439EEE39388C3CEE8EC459 /* hu.lproj in Resources */, + B7189C2F2C54A54B3AB5C3F216466FD8 /* ic_google.png in Resources */, + 0C86E322017FB0EE41297323FA93E83A /* ic_google@2x.png in Resources */, + B6F865BC534B106F368EA31F8923CEEB /* ic_google@3x.png in Resources */, + F070482F4FE2BAB29012DAB0E39641EE /* id.lproj in Resources */, + 47EA5899C0B22CC37171E11A9062D368 /* it.lproj in Resources */, + DF5C7C988590C10EF45C78A8D4167D79 /* ja.lproj in Resources */, + 69DAAD8FA321803E471DD0865A3EA960 /* kn.lproj in Resources */, + F26745D80A87F6DBBB617D7B1AA44ACC /* ko.lproj in Resources */, + B441611B7F0A39099F3A46949B0A93B9 /* ln.lproj in Resources */, + BF980319D34B50891CE50867B3EBF076 /* lt.lproj in Resources */, + 3BC1F2F0CA2F65570B44D5D06B59FCEF /* lv.lproj in Resources */, + E2007B77352C68972421B9413734BD30 /* mr.lproj in Resources */, + 5DA0CC1B1C6EDAE286F217F846C528C7 /* ms.lproj in Resources */, + B02215846A755E1CC7CEE04F580CC05D /* nb.lproj in Resources */, + B2A2330F9264C322394B3EE8A9DFCB28 /* nl.lproj in Resources */, + 025F620E8DE6EED3B6624A89A7B14B0A /* nn-NO.lproj in Resources */, + ADD0E36A420FAACCEAC7905AA5E0317D /* pl.lproj in Resources */, + C6CDDBA91529314706706F631480131D /* pt-BR.lproj in Resources */, + E43E3D08B8736D45D8E2BAB690D16EAB /* pt-PT.lproj in Resources */, + B6328917F97205BD6DAAD02FC5D26E2B /* pt.lproj in Resources */, + 023B762A93BB97ECA95535A6A05D9518 /* ro.lproj in Resources */, + 1226E8980CFB9C8990AD557278EA99B8 /* ru.lproj in Resources */, + C3A8463329338FF52B993E398488F184 /* sk.lproj in Resources */, + 9BEB85233C9D5F8A16D73F8ED7C06B06 /* sl.lproj in Resources */, + 02F5B13714B874C3002AB1F5F208220B /* sr-Latn.lproj in Resources */, + 85D57991CAAA620C3BCAE98FFC6D4BC2 /* sr.lproj in Resources */, + 49EABDC78CCC02ADA8BC3C106C02AFD7 /* sv.lproj in Resources */, + A79949097A6A6DB0E2E94B5ED30E40BA /* ta.lproj in Resources */, + 8FF5BA052B46F52BEC64AECFC7CBE830 /* th.lproj in Resources */, + 70C33E6E27C972FE599B8A3E4FB5DB2C /* tr.lproj in Resources */, + E792064CBC904A9CC45C89A4D95FA7B9 /* uk.lproj in Resources */, + ADD68D5DE76122186E4F6C8BFD098933 /* ur.lproj in Resources */, + A8CDA185643967D2FB7FEC96DCA7954B /* vi.lproj in Resources */, + B272A67E54DA88EE6D1B25B511380E85 /* zh-Hans.lproj in Resources */, + B1FA064E66162EA9C8B99589AB800A7F /* zh-Hant-TW.lproj in Resources */, + 34E1C2E17BA70DBF58D92755072E5116 /* zh-Hant.lproj in Resources */, + E679F946FDCDB8FAD74B2E59B9310D73 /* zh.lproj in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB50A8FF12777DE002FB91501C142567 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CEEB92D62C275E97C3C31E035EC00D2A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E19A058AB7F7DBDC5EE5893E774F04EC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EAC588FC0A476FF71C316002EBD69869 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EC0897EE556CE45D749AC94E16344755 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F55F7668E294AAFBC08187CC02D200CB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 034101E3F158775B3C4AD99E0745EF94 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6C46F55B8A09E4587FEEC04354F2D2C5 /* GDTCORAssert.m in Sources */, + 6529D12FE40EDF6AC2319ABA3F5680EA /* GDTCORClock.m in Sources */, + 3AFBEFD6D27A5D2FC0D30799DDE964F8 /* GDTCORConsoleLogger.m in Sources */, + 6233EF529A762C75DC0B230BB1172D57 /* GDTCORDataFuture.m in Sources */, + 47848239DE7CE0B630760AF64F106DFA /* GDTCOREvent.m in Sources */, + 84CDE1F911578AA4554F1C68B6E23836 /* GDTCORFlatFileStorage.m in Sources */, + 4CE71BDDC889ED63366C102275C1DFA7 /* GDTCORLifecycle.m in Sources */, + 8015D4C80CC0A099F478E42BFEAE3B95 /* GDTCORPlatform.m in Sources */, + AA107EC1612EC9490D8C8331BEB3679D /* GDTCORReachability.m in Sources */, + 99F6753BEB3E9CBE49919D4C42199501 /* GDTCORRegistrar.m in Sources */, + BA6E768137D38737A16803625253B55B /* GDTCORTransformer.m in Sources */, + 662B0A41D8F32A4659A1334E84B702E1 /* GDTCORTransport.m in Sources */, + 0E139B6013FF88D7B2841A9919E24AE5 /* GDTCORUploadCoordinator.m in Sources */, + 2B375405EC4015B14005396C124C4B45 /* GDTCORUploadPackage.m in Sources */, + 8151568CDB335C26709AB8834673F532 /* GoogleDataTransport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1A71101EEF5635C6B31774CAF4131C08 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4EE48AB3A8196BBBC226D648564B6D07 /* arena.cc in Sources */, + 1B73E81673E7E238C00501CE8B0A90F1 /* block.cc in Sources */, + 7B05D8EC8EE0653843D71EC1BD465CA9 /* block_builder.cc in Sources */, + AC6AAF26EFA3971640B8FDB782ADD3CA /* bloom.cc in Sources */, + D6283E19F826431F56EDA36354B77011 /* builder.cc in Sources */, + 66ADA981F5A6DB6091A81989463F261A /* c.cc in Sources */, + EB7BCF5DD7AB0F1D2738BCAB700907EC /* cache.cc in Sources */, + 896A78E7EB53DCB2813F27733F547545 /* coding.cc in Sources */, + 26995FB7C9B15A5B7B916FB103B803C5 /* comparator.cc in Sources */, + E993D71D217E1527F8F37ADB3949E862 /* crc32c.cc in Sources */, + F2F69D162BDAF8035746AABD744903F6 /* db_impl.cc in Sources */, + 57178F706DA28A0DC053EA56DB9DBD7D /* db_iter.cc in Sources */, + 77F28402B8827D867A747BCEE3668886 /* dbformat.cc in Sources */, + D0B6AB2EA69F70BEEA48705B4523C6AD /* dumpfile.cc in Sources */, + 6BA4B719CEB0771364DE59B2AB00CEE0 /* env.cc in Sources */, + 242FDA32EB04264849F3093F8D5FBB54 /* env_posix.cc in Sources */, + DCF1D766DFF35DAE3D5F3AF6D7387339 /* filename.cc in Sources */, + 82E90DE19021BDAE4572B74D3F7823F2 /* filter_block.cc in Sources */, + 9FEBAC4CB9A3FCD902C6008EBF993E52 /* filter_policy.cc in Sources */, + B033C7DABB452098F148FA326A12467B /* format.cc in Sources */, + 182F4AA1B9CECAA997F15A9F092F1B90 /* hash.cc in Sources */, + ED0E118623AAC51CF9F1549798CE585E /* histogram.cc in Sources */, + 171B588DB4215B73A93382C9B2534702 /* iterator.cc in Sources */, + 91DF6BCFEF215EA66F4A564ADCC93C46 /* leveldb-library-dummy.m in Sources */, + 79F4E4CA1B6A818B370FEB69AA09B4FD /* log_reader.cc in Sources */, + 9560DE6C92474B6264E7C5398E6E75FB /* log_writer.cc in Sources */, + 7F3E2C3C973EA28110FE842E83B94077 /* logging.cc in Sources */, + FDD9F1ABDB62000AD4EB21C5C437C801 /* memtable.cc in Sources */, + 19A227E1CDBB9C68968FE8A81AA08FB2 /* merger.cc in Sources */, + FBBD10600C3940F1221E394969DDFBBD /* options.cc in Sources */, + F3DAE3F10176D848470A4FA1DDBA8ABC /* repair.cc in Sources */, + 21CFB8F992A20FBD84EB32D6966CFB1E /* status.cc in Sources */, + 05E9C86C4FD988F2A4DCBE94344E534F /* table.cc in Sources */, + CA7959B4932ACE1F28251FF9240F03D4 /* table_builder.cc in Sources */, + 719D3EE29ED9ABD723896802B2E3540E /* table_cache.cc in Sources */, + 04B651F8B783B4C6904C66FA80945853 /* testharness.cc in Sources */, + 5A39B9D6AA724294CCB0066871D35639 /* two_level_iterator.cc in Sources */, + 7B2A3DF21F15EF978C1906EA1441C2D7 /* version_edit.cc in Sources */, + DE5F0C4CAC8F5CA01F36125D1B5A6229 /* version_set.cc in Sources */, + 3C719CF3EF732FB873BF085084EE0940 /* write_batch.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 216E9F569F209C864E5C79551608D01D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 508ADD9B844C25C9DA688D46A8D6984A /* FirebaseStorage-dummy.m in Sources */, + AA252720B5973042041CA01C9F37EDDE /* FIRStorage.m in Sources */, + C02A8677E90C8C963C54989F1D6C8F90 /* FIRStorageComponent.m in Sources */, + F62A0C4559F60B516B8350633B5202F6 /* FIRStorageConstants.m in Sources */, + 08784F7E5048AF41B6948FC917F3E652 /* FIRStorageDeleteTask.m in Sources */, + F1661085F8334C84CCD5F0B646BE2B9C /* FIRStorageDownloadTask.m in Sources */, + 4615E2A1CBD25268150CDAF59E2BD92E /* FIRStorageErrors.m in Sources */, + 4AB5AC141FC39871632CA5470D4513B7 /* FIRStorageGetDownloadURLTask.m in Sources */, + 4A78E6B8EBB9E5AB9FA957E4F8A8D0D8 /* FIRStorageGetMetadataTask.m in Sources */, + C8A036DE5E750CE1A6340BE3DDD1633B /* FIRStorageListResult.m in Sources */, + AF0F2DD74E6CF1F7060C0F09D128B58E /* FIRStorageListTask.m in Sources */, + 6A019FDF340EF64A0CCABFE6BE7C706B /* FIRStorageMetadata.m in Sources */, + 32E4D4F08762CB256AE28F683529F20A /* FIRStorageObservableTask.m in Sources */, + B14E9647B3D61648228B91DD6F1A2CB5 /* FIRStoragePath.m in Sources */, + 973F04EA375B7A592A3ED607F8591E49 /* FIRStorageReference.m in Sources */, + 33A4845D23193343A2636B220E0D98C8 /* FIRStorageTask.m in Sources */, + 7800B47B67A815BE2E4DCB87A1E22D43 /* FIRStorageTaskSnapshot.m in Sources */, + 81FCC5CC0FBD4AC46B1A3F46DA227E2E /* FIRStorageTokenAuthorizer.m in Sources */, + 622D6A2CABAF936EA29F518048A1AB4B /* FIRStorageUpdateMetadataTask.m in Sources */, + 5F1708B7AD0687C2BF83B069E0774CD1 /* FIRStorageUploadTask.m in Sources */, + 61813886EC69B09E5A4852CBA4CF992C /* FIRStorageUtils.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3EBD07698E7EFA0E27C200F51980A048 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F53CCD14D2A736AAF3B0F4194A03721 /* nanopb-dummy.m in Sources */, + 7949AE3627B387000F5A1B35762EB4FA /* pb_common.c in Sources */, + D88EBB20646F074F346F2601E0D753E1 /* pb_decode.c in Sources */, + E61992624EC5BDF25D2341D1074E43D2 /* pb_encode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4ABEF850A92F153770B2277DA98E3037 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B6A43991EB70AD84E570E24F97A05C06 /* FirebaseUI-dummy.m in Sources */, + E972E1D830854279B5B576FFF129B70B /* FUIAccountSettingsOperation.m in Sources */, + 5114E10BC50187991D597C59683980E9 /* FUIAccountSettingsOperationDeleteAccount.m in Sources */, + 26A998E7E9D58DD710A35F41CE216DB3 /* FUIAccountSettingsOperationForgotPassword.m in Sources */, + 6E0626DD94F11FB7668DE2838F52D9E8 /* FUIAccountSettingsOperationSignOut.m in Sources */, + E443F553AE1013EE57D66FB6F366284D /* FUIAccountSettingsOperationUnlinkAccount.m in Sources */, + 50CF6B7980DA6B852D3F3F25E2B38767 /* FUIAccountSettingsOperationUpdateEmail.m in Sources */, + D366A214F17917F15BD2DB071E2121EB /* FUIAccountSettingsOperationUpdateName.m in Sources */, + 3D5DA7C62B87D9300E6FE1C017D5D018 /* FUIAccountSettingsOperationUpdatePassword.m in Sources */, + 1DB9E2F55C23697926E3C5BB9FE37DD5 /* FUIAccountSettingsViewController.m in Sources */, + 15190280A7464589E58C69A821873970 /* FUIAuth.m in Sources */, + E8A95FA1B53FA8DCA22749DBE0B3D245 /* FUIAuthBaseViewController.m in Sources */, + 7D3E5684CA18BBF420A6894CF3B9CBF4 /* FUIAuthErrors.m in Sources */, + 865C483FCC318872145D059693ECF655 /* FUIAuthErrorUtils.m in Sources */, + D2B21F4E895FA7669B4F35F01AF25C53 /* FUIAuthPickerViewController.m in Sources */, + D22F32A861CFB1A862A507A81552ADF6 /* FUIAuthSignInButton.m in Sources */, + DA8DC828D080054BAE395DC6333A1906 /* FUIAuthStrings.m in Sources */, + 384EC29BF90AF67506B23E48F2F23B9F /* FUIAuthTableHeaderView.m in Sources */, + 0816CC9A4E6FAB0F54D1769AFAF40689 /* FUIAuthTableViewCell.m in Sources */, + 5AA89ABC4B1EBCA16BF7BFBEE96DDE5C /* FUIAuthUtils.m in Sources */, + 99B027C8A6EA11C63C5265F29C2ACC75 /* FUIGoogleAuth.m in Sources */, + 031A9D77AA65D0809D6C706089207682 /* FUIPrivacyAndTermsOfServiceView.m in Sources */, + 34C640803490355CD526FBA17DE1BC60 /* FUIStaticContentTableViewController.m in Sources */, + 623E683BCDF87C8235F320291CABBCFA /* FUIStaticContentTableViewManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E965BC49E36BE45CB918BF70F426071 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97EDE691559E6479F410936ADD52FFC8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 87FF583960777515289BBE8EAB91D5B7 /* APLevelDB.mm in Sources */, + 74572409E7AE0C42D50E525EDF7E970C /* FAckUserWrite.m in Sources */, + 3C682F1D7F9A25A96B74D376E64FEB6A /* FArraySortedDictionary.m in Sources */, + 933A8EE8BD5698556E6641C832E924E9 /* FAtomicNumber.m in Sources */, + 35242D43A8DB0D76B1ACBA58DA65F7DB /* FAuthTokenProvider.m in Sources */, + C449982CC108228D7A3AFE1428666DB5 /* fbase64.c in Sources */, + DB562F789B54D8C9B978FCE4633D1D3F /* FCacheNode.m in Sources */, + FD981764DC1FDE7ECB985ACAD71112FB /* FCachePolicy.m in Sources */, + 4A2E5A6D3A0427667DCC4F9965365315 /* FCancelEvent.m in Sources */, + 2583BF9A374CE74AA576004388BC8A72 /* FChange.m in Sources */, + 2907A7E8918BBE6F5A40142AD9D23BAB /* FChildChangeAccumulator.m in Sources */, + 0C4B659CE577650B21A2666B18E1A730 /* FChildEventRegistration.m in Sources */, + 649A64FB86B5C688F3F9A27628A2F0D1 /* FChildrenNode.m in Sources */, + 369AD08B841718216F3CD510659C0459 /* FClock.m in Sources */, + E57BEC68DB3A443D9F6C5F47C4654036 /* FCompoundHash.m in Sources */, + 221C335FA2AC723CFC2723B66413067B /* FCompoundWrite.m in Sources */, + 7CC2DBD8DD15F59B675BB57E34AFDBD6 /* FConnection.m in Sources */, + 706FCF28C3D142E7E95B9A8D82E777EE /* FConstants.m in Sources */, + ECB05ACB39725CA8A0B7190E26BC1E66 /* FDataEvent.m in Sources */, + 0B594E286853A9821C2EAF9FEDF2CF6D /* FEmptyNode.m in Sources */, + 5C38D5226A33ABAD5FCB1A600AE8C130 /* FEventEmitter.m in Sources */, + 29FD58AFCB84370F93925E8DAE5A72B4 /* FEventGenerator.m in Sources */, + 29E94B3A0E4CF892585A606F8064D0C0 /* FEventRaiser.m in Sources */, + 801D474941125FE5C96D1F5DECAF76C4 /* FImmutableSortedDictionary.m in Sources */, + 54A443E1D801F03B18C7EACD11EED750 /* FImmutableSortedSet.m in Sources */, + A8F02CFE73D72F2F2527B214D5506118 /* FImmutableTree.m in Sources */, + 93735D991E928025AE50476DCAF09CBE /* FIndex.m in Sources */, + ADCEC74787D20ED5DC976BB361C21177 /* FIndexedFilter.m in Sources */, + BC3C7D1A1FA9DA69185BDF00CDA4C4EE /* FIndexedNode.m in Sources */, + 7706DB609947D90EA4FE368F97C453B6 /* FIRDatabase.m in Sources */, + E3D6A62063F2E24045C0280E14A53AC6 /* FIRDatabaseComponent.m in Sources */, + 7E9873432C68540736211646DBBC7A4B /* FIRDatabaseConfig.m in Sources */, + 2CE8979B2502607A463ECE1057072C6E /* FIRDatabaseQuery.m in Sources */, + DDAD7E2134D598D2FC92464099AABACC /* FIRDatabaseReference.m in Sources */, + 5ADED25080F594D8FD890C75F682AEF1 /* FIRDataSnapshot.m in Sources */, + B822D80139D33614A8D119F71C9801F5 /* FirebaseDatabase-dummy.m in Sources */, + 6B730668021CE3D559888CE8397D4298 /* FIRMutableData.m in Sources */, + B5521C308994B7829E6626188508F0E0 /* FIRNoopAuthTokenProvider.m in Sources */, + C91366CD1844F63F6E7D9B1CF2850E1A /* FIRRetryHelper.m in Sources */, + 46DE09E96BF90F4A6F8A2B139DB6AE10 /* FIRServerValue.m in Sources */, + B82BB2163ACC8827A4936155C85F9FF9 /* FIRTransactionResult.m in Sources */, + FDBB34D54CD027C53FAEE20803153A49 /* FKeepSyncedEventRegistration.m in Sources */, + C9CC4D4690E20E77B21C7E65825BEF86 /* FKeyIndex.m in Sources */, + 2978FAC39F611ED8607050401A76B277 /* FLeafNode.m in Sources */, + A4C659C8D886BDB8389D46EC59134C7B /* FLevelDBStorageEngine.m in Sources */, + 830093FBA220D68767E42280F8AEC9A1 /* FLimitedFilter.m in Sources */, + 852E948A27E3143355DF5787C97B7208 /* FListenComplete.m in Sources */, + 2DC2C023619472E072B8BC7C9D19B14D /* FListenProvider.m in Sources */, + E4BF0A6D197372622BAD119250803FE0 /* FLLRBEmptyNode.m in Sources */, + 88CCDDE369F0D57E4768BC276812D0BB /* FLLRBValueNode.m in Sources */, + CE83BF42CF2A3D4810EBCDA1ED1C3A23 /* FMaxNode.m in Sources */, + 4B0C4ED4D4B05D0C5EAEA9637B4190A8 /* FMerge.m in Sources */, + 8526FCBCB65A3883DFE1141FB16322BA /* FNamedNode.m in Sources */, + 48F68DF275ECD44FC2CDD440C6A978FA /* FNextPushId.m in Sources */, + 5FF6349B500664F4390C8FACE38B8A04 /* FOperationSource.m in Sources */, + 6CA6A37312446FC1D71B5C60725F849C /* FOverwrite.m in Sources */, + 498E5187AB1A0FC9D170F9E0E8A06989 /* FParsedUrl.m in Sources */, + 422F4D572554D7A70D0A7BAABE0F99EB /* FPath.m in Sources */, + 530111D3B0DB8821E9CD13B69D54E8C4 /* FPathIndex.m in Sources */, + DA43EE7F5E4EAB59AC3F865E933FDBD1 /* FPendingPut.m in Sources */, + EFC82375164452FAF42A5399AA60AE75 /* FPersistenceManager.m in Sources */, + B48B4C92B1B992AB67D650AD120B59F0 /* FPersistentConnection.m in Sources */, + BD52784A213B66A87F98A9AFC2E9F181 /* FPriorityIndex.m in Sources */, + 1FAC0F4A21BC91C15C9CD4BE844BC869 /* FPruneForest.m in Sources */, + 7F8376D906B43A78D50E1ECB7214F2DD /* FQueryParams.m in Sources */, + BB203C87441D3129D2BC46D71F8B36AE /* FQuerySpec.m in Sources */, + E236C734524700EC96663DB6E943ABF8 /* FRangedFilter.m in Sources */, + FA89EF3F0A0EEE0BA38EBEF25768C0F4 /* FRangeMerge.m in Sources */, + AEA108EA49B457476CB6335C08193B15 /* FRepo.m in Sources */, + FA0D3A03C8925D8109897F7C79B8F563 /* FRepoInfo.m in Sources */, + A722B9358F15537F8597BCB54C04D08E /* FRepoManager.m in Sources */, + C1D269ECFD03FC535DFDF9DCA10B8172 /* FServerValues.m in Sources */, + E76504AF0FB9100EA2A0F85327D531FB /* FSnapshotHolder.m in Sources */, + 8AF6939EC8AF2C00EB0C89ADBAFA138E /* FSnapshotUtilities.m in Sources */, + 7D8C312EF1995BFD5FC26E164E36D9D0 /* FSparseSnapshotTree.m in Sources */, + ACD46433145A93206FCDDB6C4CDFA865 /* FSRWebSocket.m in Sources */, + AC1E95A9323BE0473FA9CDBEF06FDC98 /* FStringUtilities.m in Sources */, + 96391DCA4E520D4A1B528F7763960069 /* FSyncPoint.m in Sources */, + BE96166A6FBFAA2DC07A5D8AD147BFD5 /* FSyncTree.m in Sources */, + A24DB31365AC62EF3D68A5CCBE4EDD81 /* FTrackedQuery.m in Sources */, + E0E45289D2F45E1803D45D844CC5A112 /* FTrackedQueryManager.m in Sources */, + C144B9AC5D51D455FD59811C66C615B1 /* FTransformedEnumerator.m in Sources */, + E6EEB032CC491EC20EC6B90738C89A8F /* FTree.m in Sources */, + AD1D66E7CC1877C0ECD63BC5F1CBAF3D /* FTreeNode.m in Sources */, + F7F66C2FF8A65D04251D1547A5FB3E51 /* FTreeSortedDictionary.m in Sources */, + 800FC1C96FB62CA6443CC1CBB79BC8CE /* FTreeSortedDictionaryEnumerator.m in Sources */, + 2894DA8F3CFB72FE406F4988B1ABD9E9 /* FTupleBoolBlock.m in Sources */, + 7523A1FFBB9A4AD52DB947BFBFB95A9E /* FTupleCallbackStatus.m in Sources */, + B2019EE7CE5C1760DB056D6833E0A6C4 /* FTupleFirebase.m in Sources */, + 031341098166167255F538ED1609FACE /* FTupleNodePath.m in Sources */, + C39D7CE684DCF8EBB3706DD17FCA1355 /* FTupleObjectNode.m in Sources */, + FCB12EE6028E0377C6A2BF722F3AE80F /* FTupleObjects.m in Sources */, + 0E05314112A4239F98622C4830F4A269 /* FTupleOnDisconnect.m in Sources */, + 74AAF0FA912E952CC3296CB18DECF8F0 /* FTuplePathValue.m in Sources */, + 31D9DB944C4F02BD02B7CBB5AE188D07 /* FTupleRemovedQueriesEvents.m in Sources */, + 3C8CC8F8E043DA9D5BDA8C1F40309100 /* FTupleSetIdPath.m in Sources */, + 72AFF5873D7E384F2CFBCF8F03E56FB0 /* FTupleStringNode.m in Sources */, + D04C4A91B83601CEA9DE9B0555F3D812 /* FTupleTransaction.m in Sources */, + FE1E15FF3CC9A34A8747AC76D2115BD9 /* FTupleTSN.m in Sources */, + 1DFADAB105B05EDC592E3C8FE565F8D6 /* FTupleUserCallback.m in Sources */, + F018A89489B2EA5C5C0C4687E4844595 /* FUtilities.m in Sources */, + 5722E3D3D0D0F9BCE8C1E6A2822A9DC9 /* FValidation.m in Sources */, + FB26C46BB811C4BABB6C953C10A05757 /* FValueEventRegistration.m in Sources */, + 53775BAE742788CDA4B9961F552B5F90 /* FValueIndex.m in Sources */, + E47E4F87861D63C31906084CC3D02FD8 /* FView.m in Sources */, + ABFE52B4F220ABF754D967773D98F74F /* FViewCache.m in Sources */, + FB4FA7F5E98186AA970A658790FC86A6 /* FViewProcessor.m in Sources */, + 234AECEEF63D66064976917E97292486 /* FViewProcessorResult.m in Sources */, + F709608E527764176D6C817068EB4789 /* FWebSocketConnection.m in Sources */, + 1AF7C66EF8BE31F36E7D744D5832297F /* FWriteRecord.m in Sources */, + 63DFCFABEDE5F4FC6AA3555B6CA650BC /* FWriteTree.m in Sources */, + A9703CE2B57854BC58213AE3766D6AAB /* FWriteTreeRef.m in Sources */, + 572AFA503D9E766A04337DE770226322 /* NSData+SRB64Additions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 99C8F0F15AC77E5C7537926806AD024D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCB70A2DA3308E442CFDA42287EB8460 /* GTMGatherInputStream.m in Sources */, + CEBB8718889E7FF3DE7599F23AC5428D /* GTMMIMEDocument.m in Sources */, + 8E86DDDC4FD5A03C1A74E8A690387FC2 /* GTMReadMonitorInputStream.m in Sources */, + 288293A8A73A51D6030F539F0DEC0357 /* GTMSessionFetcher-dummy.m in Sources */, + 6F85AF013E91F455A3A1590151915C4D /* GTMSessionFetcher.m in Sources */, + 545485FF7CEA9AF03EA8900B7C955389 /* GTMSessionFetcherLogging.m in Sources */, + BF359B9968091F3A829575C466660D4B /* GTMSessionFetcherService.m in Sources */, + 488F8D1191176DE786AED6FC1824241E /* GTMSessionUploadFetcher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9CBA368F8324E647D43B9E41D7B5DC40 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A0A099D05B462309479B42964EBFA7D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9DDAA3C7E1E79D4C9C6F95B2BCCECBC /* cct.nanopb.c in Sources */, + A0A52BBB2973E7E6BF1D4E821BAB916F /* GDTCCTCompressionHelper.m in Sources */, + 8C9775088EB2BC331ED937AFFF918600 /* GDTCCTNanopbHelpers.m in Sources */, + 315D40A2C9DACF266A7BA5652244546E /* GDTCCTPrioritizer.m in Sources */, + A5041067609D4D22085164D4C09F6C5D /* GDTCCTUploader.m in Sources */, + DD81DB4F830987026CB2FE2029C65D4E /* GDTCOREvent+GDTCCTSupport.m in Sources */, + BA7AE5FD43B1E8BA87B93E0EAB39E391 /* GoogleDataTransportCCTSupport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A11F074FF69E309DAD7629265FA1E9DC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3B5E0A803F680A69149CA6CC2291C34D /* FBLPromise+All.m in Sources */, + 70B9A0900CDBA80EEBE38C19F10D287C /* FBLPromise+Always.m in Sources */, + 15BC580532B984757EF912439B2D3DDE /* FBLPromise+Any.m in Sources */, + 056AFC1435644485EAE1B012749CF09C /* FBLPromise+Async.m in Sources */, + 521833776E43C7D9F02117060F8A53DC /* FBLPromise+Await.m in Sources */, + 51D3265F64214D5D68BC9B514690EA07 /* FBLPromise+Catch.m in Sources */, + 405232561081E4DA0F2FF77DC0EFB0D7 /* FBLPromise+Delay.m in Sources */, + E5CE931AE49A8D2FF990047880BDDA39 /* FBLPromise+Do.m in Sources */, + 13FCD80568E9B4AD339C79EDED4BA2FB /* FBLPromise+Race.m in Sources */, + 0239049C823CE542E12326468AE9EDCC /* FBLPromise+Recover.m in Sources */, + 507D282C5F13D1AE71CD2F3725C38EEB /* FBLPromise+Reduce.m in Sources */, + C1E73052E8A551C53DCAE302B77A4A46 /* FBLPromise+Retry.m in Sources */, + 3B049D61D103398556EBDF0F4D703FAE /* FBLPromise+Testing.m in Sources */, + 8CADFC6D18D485950E21F6D6B7FD21DE /* FBLPromise+Then.m in Sources */, + 82456F2CA6BED1E98367781FA0B98956 /* FBLPromise+Timeout.m in Sources */, + 1D583754AB5ECEDB63D697A28FCD900D /* FBLPromise+Validate.m in Sources */, + A18B199CC3D0AC60857A9546D6BC552D /* FBLPromise+Wrap.m in Sources */, + 1BCB007B654E839010C95526E541AE01 /* FBLPromise.m in Sources */, + 8E830E3318E1AF2C9387E180B57C2A88 /* FBLPromiseError.m in Sources */, + 700E999A99823729FE3C1D4F03B17980 /* PromisesObjC-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AD75762EB133332099B72E3CC6C667EB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 41566374E119EC4270C38711624E1D01 /* FIRAnalyticsConfiguration.m in Sources */, + 49F8C0EF3592024C925614A281987956 /* FIRApp.m in Sources */, + C7732831B97DD10B28ADD656152C62CC /* FIRAppAssociationRegistration.m in Sources */, + 0D07435B8AFFBE4E95D235E7B731BB79 /* FIRBundleUtil.m in Sources */, + 4F0D14FBA4491E440C863A9489D0D7A1 /* FIRComponent.m in Sources */, + 3702D305A0003D5087C0F175605EEEB1 /* FIRComponentContainer.m in Sources */, + D2EDC1BCAB13474B206034EB856BC95C /* FIRComponentType.m in Sources */, + B1C98340BEF4FDDFB975C6A3AA83A106 /* FIRConfiguration.m in Sources */, + 37057AA414B5BE96F00FB5CC635D1356 /* FIRCoreDiagnosticsConnector.m in Sources */, + 0D69C1B4514D9905D23344A8BEB49CE9 /* FIRDependency.m in Sources */, + FA4982D49526DA1F51AFAD759C42A1D2 /* FIRDiagnosticsData.m in Sources */, + 4E74CFEC8D60E119422E2D8F20389F26 /* FirebaseCore-dummy.m in Sources */, + 07FFFE781397273584461E3DF9FC7E7B /* FIRErrors.m in Sources */, + 4AADD8428B871D93442D79F99770CC48 /* FIRHeartbeatInfo.m in Sources */, + 55683A039086EF179B1B058EC5BDA235 /* FIRLogger.m in Sources */, + 6C0AFAD79936BB20A4998D1ABC80DE6F /* FIROptions.m in Sources */, + 06EBA32B60BA67EE31AE3D2D4A6D8B9E /* FIRVersion.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BFD7F1EF6AF863993F65404FF6ABD505 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC4F78E7BB3D3F069A0D5DC47B347BA0 /* FIRCoreDiagnostics.m in Sources */, + 2C374E3E88095C9C294462506D96C280 /* firebasecore.nanopb.c in Sources */, + CC672DB8071D00ED15A3C4884A266FFE /* FirebaseCoreDiagnostics-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C84B0BF180D12428F8DB0E8555D2D5CE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FCDD595D5296BABF498C6E013D2642EA /* FIRActionCodeSettings.m in Sources */, + 0B55923174EC0606AF685E473C363866 /* FIRAdditionalUserInfo.m in Sources */, + 9C14840BFDCAF32577112F75EF357082 /* FIRAuth.m in Sources */, + E649DFA32A6BAAE9A51F363C9E602C2C /* FIRAuthAPNSToken.m in Sources */, + D53FD8331772F8F748AE94A788FEF452 /* FIRAuthAPNSTokenManager.m in Sources */, + 66C580838368369BE0956947ED4BAC81 /* FIRAuthAppCredential.m in Sources */, + 8E6B9960EC047797A00B79F62D4124C1 /* FIRAuthAppCredentialManager.m in Sources */, + 71F2B0C6705011C5B69F3862002A8514 /* FIRAuthBackend+MultiFactor.m in Sources */, + 530C06EBE16B197E16F0E8DDDFDA3CF2 /* FIRAuthBackend.m in Sources */, + 65435736A0268A60A120077901928565 /* FIRAuthCredential.m in Sources */, + 10606B75F34F9D4BA3F0CB6926EE1A2A /* FIRAuthDataResult.m in Sources */, + 81904A0CF058DD1046999ECE048DFCE4 /* FIRAuthDefaultUIDelegate.m in Sources */, + C462913B0E7361B8D2BC26260D92CD0F /* FIRAuthDispatcher.m in Sources */, + 196265062E4E5B2D9F3915B6CA0B545A /* FIRAuthErrorUtils.m in Sources */, + 2B4877E9132585C58EB4555226FE3B46 /* FIRAuthExceptionUtils.m in Sources */, + 5104242D4E06A17005611E178D6A603F /* FIRAuthGlobalWorkQueue.m in Sources */, + CDAAB6F16FDC0E93A8DC7C910853BFD0 /* FIRAuthKeychainServices.m in Sources */, + A4D53EE647F5DF3411B009F6598CC4AC /* FIRAuthNotificationManager.m in Sources */, + 1D15786A3973F469C0E325EAD86AB1D1 /* FIRAuthProtoFinalizeMFAPhoneRequestInfo.m in Sources */, + C7ED48AD37E5AA33E5D1A0C9EF266B2A /* FIRAuthProtoFinalizeMFAPhoneResponseInfo.m in Sources */, + 7FA3CADD2A8C6334A62A46877ADED780 /* FIRAuthProtoMFAEnrollment.m in Sources */, + BA599917E4E9C131A2AFFCF7D8AEFADD /* FIRAuthProtoStartMFAPhoneRequestInfo.m in Sources */, + 6A3D3A3AEFF0668302A0FF4CAB1F6554 /* FIRAuthProtoStartMFAPhoneResponseInfo.m in Sources */, + D4D9E1B57465298ECF4CBE859C5DCC8D /* FIRAuthProvider.m in Sources */, + 3D0E9CEC2B277749E2CF4CF24289DB8E /* FIRAuthRequestConfiguration.m in Sources */, + D93A68811A2AAAF52A93D0C215EEB390 /* FIRAuthSerialTaskQueue.m in Sources */, + 595648786E3F08A8DE701E00B1A50E4D /* FIRAuthSettings.m in Sources */, + B1D5CBA235E912985957637B062E5003 /* FIRAuthStoredUserManager.m in Sources */, + 511E46864C6515E5D54655E4329570A8 /* FIRAuthTokenResult.m in Sources */, + B29E685FA0F79B34DEEBD992F6CBCEEC /* FIRAuthURLPresenter.m in Sources */, + 2EDE354B4AD6B2E5DACB4B39363E6DC9 /* FIRAuthUserDefaults.m in Sources */, + C8940D872F904B13AFA6FCCFB7E34D6A /* FIRAuthWebUtils.m in Sources */, + C1C8F682F63742C103D424D8CF91990A /* FIRAuthWebView.m in Sources */, + FD4537AD06CCD6734E9259ADA0A18F55 /* FIRAuthWebViewController.m in Sources */, + FA8A2587E7695AEB9A82EA5955C49B5E /* FIRCreateAuthURIRequest.m in Sources */, + C8444B46C6A809B8F5FF7E693B527A18 /* FIRCreateAuthURIResponse.m in Sources */, + 1BED475252F19F56DAA42787AF60BDF5 /* FIRDeleteAccountRequest.m in Sources */, + D3D352E4ED4369AF438849A9EA05E907 /* FIRDeleteAccountResponse.m in Sources */, + 5E737B44E6DA0B67D19959B426B12F2D /* FirebaseAuth-dummy.m in Sources */, + EAD4D728BBB0FA93E3B229608EC26BF0 /* FirebaseAuthVersion.m in Sources */, + 9E8D4102065D27D387D10943D3B95479 /* FIREmailAuthProvider.m in Sources */, + 4845DCF4EE3FF7CB6159399E626B7500 /* FIREmailLinkSignInRequest.m in Sources */, + FB29C8A1436FB39EA84D5A2475C87C41 /* FIREmailLinkSignInResponse.m in Sources */, + C98A68B8E580F53EDFC270000666AB9F /* FIREmailPasswordAuthCredential.m in Sources */, + A04AA3C1341FDC92BA388EF29890120D /* FIRFacebookAuthCredential.m in Sources */, + 843D250BE5DB0C04925A5E9B15062E5E /* FIRFacebookAuthProvider.m in Sources */, + 30517AA89CAE84394D3DB96768672933 /* FIRFinalizeMFAEnrollmentRequest.m in Sources */, + 4D50D00D2C5E7B21A251891CF7AF88FE /* FIRFinalizeMFAEnrollmentResponse.m in Sources */, + 77DC9D2249F6CADFA28FEBC37987F41F /* FIRFinalizeMFASignInRequest.m in Sources */, + 170FA1BE2AFDCE0B8CF8562A7993E260 /* FIRFinalizeMFASignInResponse.m in Sources */, + C8947E4BC71FAD4A19AF510EE2AE1106 /* FIRGameCenterAuthCredential.m in Sources */, + D805219A599D300ACF0D2948B3C0D2C1 /* FIRGameCenterAuthProvider.m in Sources */, + C7EC59015485DECE33004C2FE3A8C271 /* FIRGetAccountInfoRequest.m in Sources */, + FB48F1055BE1DFA8C58757C1D279F640 /* FIRGetAccountInfoResponse.m in Sources */, + ABD05441BDFB77157B8020E38F6ED265 /* FIRGetOOBConfirmationCodeRequest.m in Sources */, + 767179F60EF92DCEFE95807F8290C68E /* FIRGetOOBConfirmationCodeResponse.m in Sources */, + 99FEA38F760C3B5F1AB54E2F68CDE95F /* FIRGetProjectConfigRequest.m in Sources */, + 055AB0BE1C4FCB9657F634D36CEAC98E /* FIRGetProjectConfigResponse.m in Sources */, + 2469DC3119A0B851DBE2B70FE1242BBC /* FIRGitHubAuthCredential.m in Sources */, + B277F79F14E95256EC75448495435FAE /* FIRGitHubAuthProvider.m in Sources */, + 326F3F512CC15B35883A92F7A4DA86D4 /* FIRGoogleAuthCredential.m in Sources */, + 855E190D93345AF7543B5E878CFA70D0 /* FIRGoogleAuthProvider.m in Sources */, + 9C30A623C38ADC322923C4195C145263 /* FIRIdentityToolkitRequest.m in Sources */, + D00667D5C422B0E68D072FC6999ECE75 /* FIRMultiFactor.m in Sources */, + B5B104C87A80CCB6172B25D329AF6573 /* FIRMultiFactorAssertion.m in Sources */, + 8B768769F2FCC80F02901B62AAF0AE2E /* FIRMultiFactorConstants.m in Sources */, + 263766BD77E16DF9C72E53C4A4BD1AAD /* FIRMultiFactorInfo.m in Sources */, + CC764DFBDF08AE6D71C23549529B6B17 /* FIRMultiFactorResolver.m in Sources */, + 1263598C5A64B4D36FEB0C0393F17CBE /* FIRMultiFactorSession.m in Sources */, + CACB518800D6A8DEC167FDF3F2F4CFEE /* FIROAuthCredential.m in Sources */, + 9C9E68F1D592F886CA192B393740CED5 /* FIROAuthProvider.m in Sources */, + 34E362FA2EBC79F053D69ED32EF50B2C /* FIRPhoneAuthCredential.m in Sources */, + EB1B7B371D9E895DF852FB63CA566887 /* FIRPhoneAuthProvider.m in Sources */, + A5CB9523A7B77E14A991E8C839F008EB /* FIRPhoneMultiFactorAssertion.m in Sources */, + B44DDF94C083D4E6762268A54E9E7925 /* FIRPhoneMultiFactorGenerator.m in Sources */, + 61A8C7416EC603B14526A238BB685B27 /* FIRPhoneMultiFactorInfo.m in Sources */, + 6F62B2A2A17D5EA43DD35514513722AE /* FIRResetPasswordRequest.m in Sources */, + 5829B9395462EC3F409DC8AEF8F106A4 /* FIRResetPasswordResponse.m in Sources */, + E200A7C70F0C4C52A501EB305742E8C8 /* FIRSecureTokenRequest.m in Sources */, + 003BC15B01B115BE46E8FAA7DB3315FA /* FIRSecureTokenResponse.m in Sources */, + 61D67B5C333F80E824E37DF5BFF079C5 /* FIRSecureTokenService.m in Sources */, + C4F860796ED8DFD85800BACDE3A1B8C6 /* FIRSendVerificationCodeRequest.m in Sources */, + 20D8D94C042B585E36891307D12452B3 /* FIRSendVerificationCodeResponse.m in Sources */, + 621138AF31CC70B47190D5008ACC1F11 /* FIRSetAccountInfoRequest.m in Sources */, + EE8AC38A9ED2EA24296D80E546653DEE /* FIRSetAccountInfoResponse.m in Sources */, + CE53C8C76885412AC967D02641CE4994 /* FIRSignInWithGameCenterRequest.m in Sources */, + 3966411927DD463FB7CEA504A9188D8E /* FIRSignInWithGameCenterResponse.m in Sources */, + FABE7EBD29A940330700F0EE7E959A8D /* FIRSignUpNewUserRequest.m in Sources */, + 151C90C5A2D4B8809BFB331B2ECFC28B /* FIRSignUpNewUserResponse.m in Sources */, + 8EF100949FE2D45B954E1E88C95D268B /* FIRStartMFAEnrollmentRequest.m in Sources */, + 3F1F361AAA196EC3433653171B98900A /* FIRStartMFAEnrollmentResponse.m in Sources */, + D59E573660F805F91AD5AF8E75A5F087 /* FIRStartMFASignInRequest.m in Sources */, + 01561D513FCA73D5A6E6AB77DA1FA9A6 /* FIRStartMFASignInResponse.m in Sources */, + 5ED0F1610C2E873A4841325B13410A34 /* FIRTwitterAuthCredential.m in Sources */, + 17993EED5265C3BF7DC731E399AA339F /* FIRTwitterAuthProvider.m in Sources */, + 2D48DFD7C608A4732D6AC061FBFDFD28 /* FIRUser.m in Sources */, + 5BCEEF371F011913FB019D3085CDC9BD /* FIRUserInfoImpl.m in Sources */, + 917C7410F4D06546F3C2ACD632669FD6 /* FIRUserMetadata.m in Sources */, + DBB9A02097B659853F4B886DB3B20635 /* FIRVerifyAssertionRequest.m in Sources */, + 6C89DB341AA1CA45037B037568C6761B /* FIRVerifyAssertionResponse.m in Sources */, + C77314526A32BBAFB4B100AE8C709BDB /* FIRVerifyClientRequest.m in Sources */, + 350DC6598D772740CB7F40C7638023B5 /* FIRVerifyClientResponse.m in Sources */, + C51EBC40CA60F7415E1F235A49C93B24 /* FIRVerifyCustomTokenRequest.m in Sources */, + 6AA90E0D3A5FA0045509804BD80D0C9A /* FIRVerifyCustomTokenResponse.m in Sources */, + 120CD82B71E3E547CF68417454F0DB5B /* FIRVerifyPasswordRequest.m in Sources */, + 74CCB49825E488983AB3A0C14E885DC8 /* FIRVerifyPasswordResponse.m in Sources */, + DA8E5C7DB11C5D8B3F1C6713C4A2245E /* FIRVerifyPhoneNumberRequest.m in Sources */, + 75CDB4E7399EC92E06E5575AF06A0492 /* FIRVerifyPhoneNumberResponse.m in Sources */, + 055488955277E0E9136A6DFE4651B9AA /* FIRWithdrawMFARequest.m in Sources */, + 06283E1D781D85AE9430AD9F1AAE3615 /* FIRWithdrawMFAResponse.m in Sources */, + 66BD54F510355737D99703E4AB1A7BC1 /* NSData+FIRBase64.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45C550ED36B0C2816AA743B9875AE93 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F1A5E7E7CFF3781A8E6FCB4D33DFA90 /* GTMAppAuth-dummy.m in Sources */, + 941CDBBF8A276F9D7A78A1491F0847F3 /* GTMAppAuthFetcherAuthorization+Keychain.m in Sources */, + 81F22F8E4759DD80E1AB340B47F7EEFB /* GTMAppAuthFetcherAuthorization.m in Sources */, + 233EBF79D6993F0C86E1B7BBC565F09A /* GTMKeychain_iOS.m in Sources */, + 6868432FB3D97578C24EBD4B94D3D8D3 /* GTMOAuth2KeychainCompatibility.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DD1A38B09272920CB5F3597DE401D6B9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CFF8F6CC09FACC4F1DCF0435BD33315B /* FirebaseInstallations-dummy.m in Sources */, + 57A5799EE36CD3738E4AABC8602C7EFE /* FIRInstallations.m in Sources */, + 8F99420AD42119A0A9F8CC4A4AEE9DF7 /* FIRInstallationsAPIService.m in Sources */, + 1507F4EFA5216031D5CF868136A835C1 /* FIRInstallationsAuthTokenResult.m in Sources */, + EF6FEF068B4C41B1EC133F11C985EA70 /* FIRInstallationsErrorUtil.m in Sources */, + 3401AFF2A97BCEEF3FE0B3D9DFB23C7E /* FIRInstallationsHTTPError.m in Sources */, + 028073448A6EB2523EB06EEED522C673 /* FIRInstallationsIDController.m in Sources */, + 7AB0F39B04F5C0445C3262C0A3CE7C76 /* FIRInstallationsIIDStore.m in Sources */, + D30D073687B9EB2E598796EE7983B567 /* FIRInstallationsIIDTokenStore.m in Sources */, + D29645BA2B207B4B26F99D5359D81D3F /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */, + F9FEE6018327821CC1B6ADDA9F505815 /* FIRInstallationsItem.m in Sources */, + 5FF453EA030631028E30C6BC3D4C4DEE /* FIRInstallationsLogger.m in Sources */, + AB04A8A3DFE879B7205875E30A8ED6EF /* FIRInstallationsSingleOperationPromiseCache.m in Sources */, + 5C20C1714B7AEE5D603261CBADAC7DA8 /* FIRInstallationsStore.m in Sources */, + 3858E1DA25778132A8EF8E7F1C27F8B9 /* FIRInstallationsStoredAuthToken.m in Sources */, + A6D861F8BA510EE9B3D14423A664DDE2 /* FIRInstallationsStoredItem.m in Sources */, + 923CB835DD8318AD7EB99EDEC0B14C8C /* FIRInstallationsVersion.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EE8987EEF880C18D10981FFDD9D8A56F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E0FAC15F4F36C52260C7EBBCCF82F9BF /* GoogleUtilities-dummy.m in Sources */, + F08D2D2BC131436E99F047461CF3F534 /* GULAppDelegateSwizzler.m in Sources */, + 7DFB5C1B35041DF23880D96130900E54 /* GULAppEnvironmentUtil.m in Sources */, + 738C1C16A1A5959F3CFB28472DE51A70 /* GULHeartbeatDateStorage.m in Sources */, + 32C15D7F433779E994CB212E90665040 /* GULKeychainStorage.m in Sources */, + A784F41C2D045F1AB7E9F394FBB00688 /* GULKeychainUtils.m in Sources */, + BA54A3709D477EFE277F2DB73772979E /* GULLogger.m in Sources */, + 0A828513A4E67FA6621CB3672B9B93FE /* GULMutableDictionary.m in Sources */, + E3CA70647D730C7F4AA6E803A8B7D45B /* GULNetwork.m in Sources */, + 8A2E4C6A0316CC01B77F93A37F110FDE /* GULNetworkConstants.m in Sources */, + 3E300FD7FB5B126C68BB81C83C32F848 /* GULNetworkURLSession.m in Sources */, + 69BBE3F9F46DF14F6EC457ED81AE0615 /* GULNSData+zlib.m in Sources */, + B727B4805AB5FEE5B5DF4546FB713DF1 /* GULReachabilityChecker.m in Sources */, + D89C53911B9E13A27CF080ECB80A9C15 /* GULSceneDelegateSwizzler.m in Sources */, + 442D681AB88C1CEFD0857BD3B4BE323B /* GULSecureCoding.m in Sources */, + 1202EF6BAEF6D33CE6C057BA2911D3BE /* GULSwizzler.m in Sources */, + 27431C2385575FFD450126CB6958FBD9 /* GULUserDefaults.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA40C5373E6F05613AE4464C1A8C3500 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E23750FE124E07AFF21DB9AC9542BCE /* AppAuth-dummy.m in Sources */, + C359863B7FF01F6B19CDA89D30126EE6 /* OIDAuthorizationRequest.m in Sources */, + 075E34225D4CE71C2F2FC63FB9CE0CA3 /* OIDAuthorizationResponse.m in Sources */, + A1AF5BF63FEEA98CB2D165039170E6F7 /* OIDAuthorizationService+IOS.m in Sources */, + C23F697B76C8D3242F232D958E0C00E3 /* OIDAuthorizationService.m in Sources */, + 152481DAFF8FA47F61BB412784DF31E9 /* OIDAuthState+IOS.m in Sources */, + 06953BA616880F876D31CECCEDC11105 /* OIDAuthState.m in Sources */, + 16F96D0B2EE7EBED059FF327B8E90E5E /* OIDClientMetadataParameters.m in Sources */, + D90A3C067FE031487AD6F53979803AAA /* OIDEndSessionRequest.m in Sources */, + F63C85CE50933EE6BDB86F9C87253F1C /* OIDEndSessionResponse.m in Sources */, + 2D8D67C396A0A1A33320AB9924E9DB42 /* OIDError.m in Sources */, + 2095003DC22D3D86A334AA1A1561900D /* OIDErrorUtilities.m in Sources */, + 0A83C33151A74978B5009466B16AA320 /* OIDExternalUserAgentCatalyst.m in Sources */, + 2B9DE014CBDC27683B204852475EB8A6 /* OIDExternalUserAgentIOS.m in Sources */, + 79117048A3C4F245532CAE57EE37901A /* OIDExternalUserAgentIOSCustomBrowser.m in Sources */, + 5C43E64B8DFCE99DD92F62D538C0DFF0 /* OIDFieldMapping.m in Sources */, + F246177F1215CDBE9AB3B1BB58624C04 /* OIDGrantTypes.m in Sources */, + F47BF5598DBEDEB0A44679023AFC7E66 /* OIDIDToken.m in Sources */, + B00AF14E70C26C9D19EDB3AB4F04123E /* OIDRegistrationRequest.m in Sources */, + EE329DF01337A5B2040D3D7532BEB766 /* OIDRegistrationResponse.m in Sources */, + 22BA02A9AF9DDB1A405D82C84953B295 /* OIDResponseTypes.m in Sources */, + 705E22C52493D0AEDE135873802B54E0 /* OIDScopes.m in Sources */, + 17587A84F44BB3F9BBE44E3F0BF91929 /* OIDScopeUtilities.m in Sources */, + A837179BAD5CC1FFC6BFAC2C5C67E334 /* OIDServiceConfiguration.m in Sources */, + 2C034AC52FF9090141709228E7A67121 /* OIDServiceDiscovery.m in Sources */, + 3F609DF53628B2F834F882C40F39C99C /* OIDTokenRequest.m in Sources */, + 3989F5BDEC4A21202F727FB35ECB9E4D /* OIDTokenResponse.m in Sources */, + 95D660DE029B3057EF7922C44E75B6FF /* OIDTokenUtilities.m in Sources */, + 218BA22AD876AB6E19146F5A9ABC8F5E /* OIDURLQueryComponent.m in Sources */, + 86C6E9D09DD9A2F765ED9CF5F981560C /* OIDURLSessionProvider.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDC5C1A195E2E38C77F9932070CEC8A9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BF18BDF2A230234AC681FC729A197F05 /* Pods-MyExperiences-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 058CDD771575B7F2702CD70417C4FA33 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = F91D960E25A246F641BB599B261122C9 /* PBXContainerItemProxy */; + }; + 061C01B3BE32CDA65FF174894B84F457 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 98763D00A1261E2C77540ECBDA0197F6 /* PBXContainerItemProxy */; + }; + 0DF43D9FBFF86CC4E26F38AA656A8CCA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 312219644023E298DA40F1DD75C8DA11 /* PBXContainerItemProxy */; + }; + 11482A16E2499B32E1F9E8942C504A82 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 010F07B1C767CAD81018B2270BDB1848 /* PBXContainerItemProxy */; + }; + 1C909B19E05F29CBFA9C74E247EF13D1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = 44C02AF115EFCC36544FE7A86B0471E4 /* PBXContainerItemProxy */; + }; + 1CC9595BE02776E2952547CCF0D05ED2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 6EB53DDD74D0AA3D084AA70752582019 /* PBXContainerItemProxy */; + }; + 1CCB5F9ABA8C28428C910FA4E9466868 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = BC7CF60269466E79C607EF2A2D1EB2E6 /* PBXContainerItemProxy */; + }; + 1FAA13BA586F7B8D714A0FC57EDBA63D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMAppAuth; + target = 8627999EF1D5E93E13DAFF580DA8CDCF /* GTMAppAuth */; + targetProxy = CBC29057F9DA163AA37E9D817574A9D0 /* PBXContainerItemProxy */; + }; + 211FFB9BAE629EBD1FA548E8B6019FC6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = AFB753BAE2F4F5EBBD74FB3A18D2CD2E /* PBXContainerItemProxy */; + }; + 21263CB0995072855461EC88B90EE6C4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMAppAuth; + target = 8627999EF1D5E93E13DAFF580DA8CDCF /* GTMAppAuth */; + targetProxy = 525CA5CA0973E2865F15D715DDFAF804 /* PBXContainerItemProxy */; + }; + 242C2BEED77BDC312A3E12D2B887AEDA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleSignIn; + target = CAD3534FC55B0333104E5117C0A9A324 /* GoogleSignIn */; + targetProxy = F2F7AB46ED380C7679FD87C608E79235 /* PBXContainerItemProxy */; + }; + 27917D894565B334081F9B17D91FD3B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = C89B6FC29E6485480F8DE9C1C0F308FD /* PBXContainerItemProxy */; + }; + 27FD3D09FA099C1583365C9BE90948A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = C5C8C97EA08D7637A211D3FCFC914B1A /* PBXContainerItemProxy */; + }; + 2B20806AD06B7E23F12FFA35C1265843 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = 126018A904814EA99D27EC03B05B36A8 /* PBXContainerItemProxy */; + }; + 2B621894FE08AF8DE575849709762BE1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 94538A05E1DECB8C9FE5BF8B2256F244 /* PBXContainerItemProxy */; + }; + 2C0EC82F9C670F1DC5657EFD705B724C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = DD8C535932A07608FAAA02FC95FD2C3A /* PBXContainerItemProxy */; + }; + 37C67F0FC57A90D9601A609C4B3217DB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = B26047A963065253F0D379249059EDF7 /* PBXContainerItemProxy */; + }; + 4466D3DE2D8BB2D0953C98C7431C668D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AppAuth; + target = 5C642AA10FB29936669CC269F42079C6 /* AppAuth */; + targetProxy = D4360B33CFE1C713F022BA548944EBD1 /* PBXContainerItemProxy */; + }; + 44ACA436AFF162787B57713C15CE151E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = 58327700A92C5323F432AFF59DE99969 /* PBXContainerItemProxy */; + }; + 55EC04FEDD874A1939C5BE4BF5F0D4C1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "FirebaseUI-FirebaseAuthUI"; + target = 4F91D2ECAC31D494531E121B750D88A5 /* FirebaseUI-FirebaseAuthUI */; + targetProxy = 4E2A37CD36BD7FD428D9385A5D248C93 /* PBXContainerItemProxy */; + }; + 55F1D58B062056D5BF67D2D266C40E76 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseStorage; + target = 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */; + targetProxy = FFDCDD20625795143B0591AFFE295B52 /* PBXContainerItemProxy */; + }; + 598C058565BA97E2F0BC79E21739F980 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AppAuth; + target = 5C642AA10FB29936669CC269F42079C6 /* AppAuth */; + targetProxy = 7829C8A09AA6FE1144920B12865C4F56 /* PBXContainerItemProxy */; + }; + 5A158FB70B0CC76E4EC4B49EC5D083A7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = 71158069FD5DAC3AF5A98F3D3A0285A0 /* PBXContainerItemProxy */; + }; + 5AFFF32F01F2F37D9F46F79164076DC7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 340452A7367705D2113B5D88428CDA52 /* PBXContainerItemProxy */; + }; + 5F2D4959316FC456115F4CC1505E0929 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = AFD7E3A2A6E9E918AA33CE4549DCB080 /* PBXContainerItemProxy */; + }; + 6ACE31262D9464F42FB02A8DF2B4AF26 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 366053566D1F4F9AEE9DA3436BF8AC2B /* PBXContainerItemProxy */; + }; + 6CC16101294855C178FAE376855B1E0C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AppAuth; + target = 5C642AA10FB29936669CC269F42079C6 /* AppAuth */; + targetProxy = 28E28E2BDEE7C508774A40F5BE7A319A /* PBXContainerItemProxy */; + }; + 722C50D47EE62F1F1D11E9D3AABB3427 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = A16D31BE4F883B9CA8546DDBE266BC2C /* PBXContainerItemProxy */; + }; + 729CCCAD8A0BC70FAB53583BF03B29D8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseUI; + target = 6D45934038562DBC96227173D041A9C1 /* FirebaseUI */; + targetProxy = E71226CA418EB410327E4AA7178A6FBB /* PBXContainerItemProxy */; + }; + 78F437B92AD2A3917E852E339CF694A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = 897E13BEF582159D0B0D986EE4B10357 /* PBXContainerItemProxy */; + }; + 799FD051C980C75E7031F22B9A3F3E3A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = 59EB9FD842075F38F65D1C01FCB87B52 /* PBXContainerItemProxy */; + }; + 7FCEDEC03E910C5A23F8A29F72997DE9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 071D8D247AAD714748EAC34CD9F73348 /* PBXContainerItemProxy */; + }; + 80AA0396EB3E3860BD6F20227D329362 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "FirebaseUI-FirebaseGoogleAuthUI"; + target = 6051175E4E4C37209FBE2BF5BE4627BD /* FirebaseUI-FirebaseGoogleAuthUI */; + targetProxy = 35E3B3F7AC5DC47D4F258436E0E9E3C8 /* PBXContainerItemProxy */; + }; + 80C3C75F2547C59CC1E12F760E0356E6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 89BAB4E0A3FD8999A33C83637D2FCBD7 /* PBXContainerItemProxy */; + }; + 8D9964CFF970F8122123D5465614395A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 4D25F6B4E0A10549DC7CEA156700A207 /* PBXContainerItemProxy */; + }; + 8F31BBD06489C0BE8183A7B761920DBD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 9C2D21C8DF3376328FDEC9431B8B8DEB /* PBXContainerItemProxy */; + }; + 90C02305739A6B4287D36F1A6679A248 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = AE8690FCA2E55E8CD7E79A02A8041A40 /* PBXContainerItemProxy */; + }; + 9129CC909DCF71C59C68BD1E6F3DC1C2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = C6D8AA5C1C0D1DA09D9F3ED749DC5FD2 /* PBXContainerItemProxy */; + }; + 955C99E32D560318496D3EE66A0FCC85 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = F35AF7AB340D596F14D7D42CCAB7EBE9 /* PBXContainerItemProxy */; + }; + 9B701E31E7E3EA1335E62F6BF220C3CF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = D284B0AC1AF1E545BB972919C4F5A1CD /* PBXContainerItemProxy */; + }; + A2A63968F85F1E6F7EDCA30A664A72C7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = 4B56396745027BC82A40601D428C27F5 /* PBXContainerItemProxy */; + }; + A5945ED690D018F5F3BAC40EB80112D1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuth; + target = 6AE4A3D573DED275B034E20506596C62 /* FirebaseAuth */; + targetProxy = 6C26D7C9E53F52F612D00E87253D5FDA /* PBXContainerItemProxy */; + }; + A8DF7E6143B9E581DA6CCE9438DDCE46 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 1744D66CFD389BDDB1564ABB3C0CB2C3 /* PBXContainerItemProxy */; + }; + ACE867CE743A04FCEE725CDB1A868026 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = B725E1CDA4D0FBDE46907D3D1BD4DDC4 /* PBXContainerItemProxy */; + }; + B33B63DD38C271F72B168288EDBAFE03 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 3542E1C31EAABD4FB4866C17CE2EFBAB /* PBXContainerItemProxy */; + }; + BB9DF6DCD7E0A950C7162EC456618B30 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleSignIn; + target = CAD3534FC55B0333104E5117C0A9A324 /* GoogleSignIn */; + targetProxy = C336B15FD74D6A57E675FBEEF914F09B /* PBXContainerItemProxy */; + }; + BDBAE6F51DD6B1FAA6275A31398BA7F6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = BBDD0024DF8A3C8B835FFC73AEF9F5D6 /* PBXContainerItemProxy */; + }; + BFFA99EB13B6A8F396C04EC1A6450BEF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = 57455EE8C938F1E79B9092051E3C2D6F /* PBXContainerItemProxy */; + }; + C16CA301A08D3A7F79032732793C3D2D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 2B2F6F4A87E5302955A2730AE4F31E2E /* PBXContainerItemProxy */; + }; + C76C2A7BB91DEE6AB780A019BCEB847D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 668B7A11F521D0EB1F41665973A46D04 /* PBXContainerItemProxy */; + }; + D35079C7BFFC9D393376AB8428F319E0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 075D5B5B0C185012243AAA04E44230A3 /* PBXContainerItemProxy */; + }; + D99C37BE936E12B58FC32858233436EE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = 335F95B6CE168385BA93EB8B9BB517C7 /* PBXContainerItemProxy */; + }; + DA37C675CB443F217AF335EC7B4EC00D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseStorage; + target = 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */; + targetProxy = E981732EC7122F9C1BD1A4EE59406149 /* PBXContainerItemProxy */; + }; + F00E3216A1D9517824DC84147D1B48A9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = BD278C26B16F39574329F7F8395C8D9B /* PBXContainerItemProxy */; + }; + F010753889728A35377801C8F15D17A9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = ED8943D69B5E68F0DF5139DE83ACDDDD /* PBXContainerItemProxy */; + }; + F18A38D42B84652687C39B25FA2E74E1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = A0CA2737162685D26F3D72473DF55E16 /* PBXContainerItemProxy */; + }; + F5214B9E4EEBC5649914D20EC00DC06D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = 1C22F2299104707ADE6EC1A1BC085CE3 /* PBXContainerItemProxy */; + }; + F62F221BD8BA6C3E17D5C844993E95CB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuth; + target = 6AE4A3D573DED275B034E20506596C62 /* FirebaseAuth */; + targetProxy = 3A0F3C20D57137EA50313B27510D20A2 /* PBXContainerItemProxy */; + }; + FE620EB6798E24167774587C5BFE2DA8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 0731191EEE5227426FC3E06F38030119 /* PBXContainerItemProxy */; + }; + FE7A852F0E43A74DD415897DD5E4BDC2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = E77389552F5BAF3B750CBB3711CB5975 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0568B3BC9A7D442A26379CC12DD08AC1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE31FD42BB2863C4D9CAC980F8085F1A /* FirebaseCore.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 093E2EB133C7BCE81EF107A2B0835AE3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E6E77D4731AF3B4301FA924924F6AEE6 /* Pods-MyExperiences.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0B27B00068AF0A536D52C438D026D833 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D203DE15B02674646A391ECDC4236920 /* GoogleUtilities.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0C1611403BD7D84AFAF332BD69336DFC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 47BF9B1F1B231A09680C4D56CCE235B4 /* nanopb.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 12228DB6CFFC713214849E08375D9731 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 24C633FD22C7C3FC566586ADA13E5100 /* GoogleAppMeasurement.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 18D62B8ADFDFA0A86D4408A60822B89C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BB4C2140E68F6C9C0DA2ED701FC0DADB /* Firebase.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1AFF790D3596D1EDF3BA105F7C39B1DE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 62E8321425614316CDA53111C50B49A1 /* FirebaseInstallations.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1B550B63A0A0CA3A1FA5FC2AC8BF3210 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92379D905E987E03974E31D4B6F3488 /* FirebaseUI.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/FirebaseUI"; + IBSC_MODULE = FirebaseUI; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = FirebaseGoogleAuthUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 1D051F9B5C038C830C22FDD03A43E218 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F405BDCCD96FE6F1912403A62DAE2B04 /* leveldb-library.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 2282AF89767243134694E4431405425F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DF010ADE9F5D95CEA7163C271DF4AF14 /* nanopb.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 24C00BCC9EEF4B29987D38C1C8A260FE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 462E033744D3959BB491ED645DF42A70 /* FirebaseAuth.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseAuth/FirebaseAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseAuth/FirebaseAuth.modulemap"; + PRODUCT_MODULE_NAME = FirebaseAuth; + PRODUCT_NAME = FirebaseAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 27B0EB4C7A9A15F0CCC3E870C5284B83 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92379D905E987E03974E31D4B6F3488 /* FirebaseUI.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/FirebaseUI/FirebaseUI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/FirebaseUI-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseUI/FirebaseUI.modulemap"; + PRODUCT_MODULE_NAME = FirebaseUI; + PRODUCT_NAME = FirebaseUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 30A45983CA15662DA326EA1E9A9CA19F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A99030435F8DB28FCCE7B7B4819BB6C5 /* GoogleSignIn.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 33C224F3DF0581562DD9A9723210E4DD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C6CF3BD228981A8B6F7FA16F10B7BE6B /* FirebaseUI.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/FirebaseUI/FirebaseUI-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/FirebaseUI-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseUI/FirebaseUI.modulemap"; + PRODUCT_MODULE_NAME = FirebaseUI; + PRODUCT_NAME = FirebaseUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 356B259E3F15B5C01FFF2308D144D082 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0B94E6B8AF33C56D68D4AD9BAA5FEE2A /* FirebaseCore.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 39B585DECAB0FF087BFB93F1F90CB82D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B2C32D7546A54979C5057A1181763D1C /* FirebaseAnalytics.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3BFB49A0C652DF4A91F6D35EE641F051 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C48ADF74490C4A45C87650023E850992 /* AppAuth.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/AppAuth/AppAuth-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/AppAuth/AppAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/AppAuth/AppAuth.modulemap"; + PRODUCT_MODULE_NAME = AppAuth; + PRODUCT_NAME = AppAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 459BAC11166CA4D3C2764E641D0CE5CD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C6A572D31316806D9DE6D2194E98FBE0 /* GoogleDataTransportCCTSupport.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 49A7DDAD23F378F1D892EA94C4F3CEF4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 12AA880F6A063BFB19894928A16F070A /* GoogleDataTransport.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 4A91E459BFB73EACB17ACB7345B43B34 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F3F5B906825D61484CAAA87789BD98D5 /* leveldb-library.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 50A010BCA7DB6AF2219E5F128D170AF8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 78DA4E0D7190329C4F87CE06689EF217 /* FirebaseDatabase.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 522DAF60E5909B87D5B8AD7A15C94676 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5269D9C7D55A1DA1FED6C3B459D98F96 /* GTMSessionFetcher.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap"; + PRODUCT_MODULE_NAME = GTMSessionFetcher; + PRODUCT_NAME = GTMSessionFetcher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 52787EF8BFB561F854D16775A1FC09BA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 16A005FC0FE4E4802BA3D80F616EDBE2 /* FirebaseCoreDiagnostics.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 5567E8B826B3BD596A640CF97C9AACB2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C6CF3BD228981A8B6F7FA16F10B7BE6B /* FirebaseUI.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/FirebaseUI"; + IBSC_MODULE = FirebaseUI; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = FirebaseGoogleAuthUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 5A9F4D90612A2879C23028EAFF4BA473 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 15F815C512EA7B4CD9D9AB719AABC2DF /* GoogleUtilities.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 68262571B9D365A7C9E4A33747CEC673 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 813EE38656EDBC2CE28989B9B8E3D86F /* GTMAppAuth.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMAppAuth/GTMAppAuth-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMAppAuth/GTMAppAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMAppAuth/GTMAppAuth.modulemap"; + PRODUCT_MODULE_NAME = GTMAppAuth; + PRODUCT_NAME = GTMAppAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 73D98C6C7FC81825EC98891BBE55F736 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 00E9ACE5B742B168BBAD473E28C5130C /* PromisesObjC.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 79A0904720F9B7D44B4121F5E9FA69E5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6969333C9227391D15AC78F611999F9B /* GTMSessionFetcher.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap"; + PRODUCT_MODULE_NAME = GTMSessionFetcher; + PRODUCT_NAME = GTMSessionFetcher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7AC1F21D12520088001C8A71331780AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92379D905E987E03974E31D4B6F3488 /* FirebaseUI.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/FirebaseUI"; + IBSC_MODULE = FirebaseUI; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = FirebaseAuthUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + 7BCD2751B9DFC93B2BF209BF9C529EA9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C2C0C1E05732AAA942EE2412CFBE94DB /* FirebaseStorage.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage.modulemap"; + PRODUCT_MODULE_NAME = FirebaseStorage; + PRODUCT_NAME = FirebaseStorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7E8ADF207D12C725E7F8D9840D9D7F40 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A43B99F4F9A7AFE85D8AC61C327BA44C /* GoogleSignIn.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7FC52C4287BE3F8FD34886CAD27809E4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 325AFB4CBACC98A3F8EC79BF19DDAE61 /* Firebase.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8870B2195E15DA72E95A381A5CC95526 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 53F0F09CD2905B3297B81557EFD55B0F /* FirebaseAnalytics.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8B38C0F50C50D0FA6487274AF29DBC37 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C0B61C5273C700F880D6781D3AF1920 /* FirebaseCoreDiagnostics.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8ECBD9B9212CC23FB5D15765A5058ED0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6B0125857F5D4327999FD36E51BC633B /* FirebaseStorage.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage.modulemap"; + PRODUCT_MODULE_NAME = FirebaseStorage; + PRODUCT_NAME = FirebaseStorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9C3DB456C2F3B1F42F7BE5283909055E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9D19FDA9CE8895E11678DDCB7526EF93 /* GoogleAppMeasurement.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A480657CB81C9FB60992EBD8B873423E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F31501F6FF6000C04AC321C6A82873AB /* FirebaseDatabase.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B01CCD18817755E97B52F769301CCB3F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0F948F6E03F0241D6A276C287317A33B /* FirebaseAuth.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseAuth/FirebaseAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseAuth/FirebaseAuth.modulemap"; + PRODUCT_MODULE_NAME = FirebaseAuth; + PRODUCT_NAME = FirebaseAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B20D1D61EA67C0A56F1E7658B410D49C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D508A6DD4E5CBF53FD46E6F4ACBE445F /* PromisesObjC.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B55D9D245E017E9993D5EC86ADDD2380 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2BA69B89E7BA669D98FB1669F1953521 /* GoogleDataTransport.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + C1E41698E991715C1A1292E243573CA2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7F6F1EC69708D5FC3C78D21BD2150788 /* Pods-MyExperiences.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-MyExperiences/Pods-MyExperiences.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + CEED3BE9D9BBFC1B5BE09AA928ADAB77 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 451DB994D279FCD5DC50A8225E9DEDAE /* AppAuth.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/AppAuth/AppAuth-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/AppAuth/AppAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/AppAuth/AppAuth.modulemap"; + PRODUCT_MODULE_NAME = AppAuth; + PRODUCT_NAME = AppAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DCD49C2219A7E0938BBD502EB5B35F9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C6CF3BD228981A8B6F7FA16F10B7BE6B /* FirebaseUI.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/FirebaseUI"; + IBSC_MODULE = FirebaseUI; + INFOPLIST_FILE = "Target Support Files/FirebaseUI/ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = FirebaseAuthUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + DF01653A78F4511C681F7E0431B382B2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D8E51FA8CD9E9B5E68B3EC07F9539215 /* GoogleDataTransportCCTSupport.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DF6547FA380F125F01492484CF99E944 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 46208F8F4DA72F736C3CA97FBF8633E5 /* GTMAppAuth.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMAppAuth/GTMAppAuth-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMAppAuth/GTMAppAuth-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMAppAuth/GTMAppAuth.modulemap"; + PRODUCT_MODULE_NAME = GTMAppAuth; + PRODUCT_NAME = GTMAppAuth; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DFD9D19FEEBF98DE271D7FBABCB845B5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + F1ED442F1FAFC1C840B3B060D8200DF6 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3D5C7F511F0129F1612DE2D4A8CE947B /* FirebaseInstallations.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + F5F04600F5626DC980F02790D1ED2C19 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0A2F227A2B6E041D0DE9C55C0A673550 /* Build configuration list for PBXNativeTarget "GTMAppAuth" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 68262571B9D365A7C9E4A33747CEC673 /* Debug */, + DF6547FA380F125F01492484CF99E944 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2562FCEBD94AC96F30940CF976E58B73 /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 50A010BCA7DB6AF2219E5F128D170AF8 /* Debug */, + A480657CB81C9FB60992EBD8B873423E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 311E5E7F5B7EA3517988E8CC09918B82 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9C3DB456C2F3B1F42F7BE5283909055E /* Debug */, + 12228DB6CFFC713214849E08375D9731 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 35458B72DBE937B906DFEB68EB76D03A /* Build configuration list for PBXNativeTarget "FirebaseUI-FirebaseGoogleAuthUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5567E8B826B3BD596A640CF97C9AACB2 /* Debug */, + 1B550B63A0A0CA3A1FA5FC2AC8BF3210 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 399FEFEFD30AFF53045B521C98EB302D /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1AFF790D3596D1EDF3BA105F7C39B1DE /* Debug */, + F1ED442F1FAFC1C840B3B060D8200DF6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3BC9A595AD3BC93490E6CBCB50B2E53F /* Build configuration list for PBXNativeTarget "leveldb-library" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D051F9B5C038C830C22FDD03A43E218 /* Debug */, + 4A91E459BFB73EACB17ACB7345B43B34 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DFD9D19FEEBF98DE271D7FBABCB845B5 /* Debug */, + F5F04600F5626DC980F02790D1ED2C19 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A3C9ED2226B899F6727A4FA61E98A07 /* Build configuration list for PBXNativeTarget "GTMSessionFetcher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79A0904720F9B7D44B4121F5E9FA69E5 /* Debug */, + 522DAF60E5909B87D5B8AD7A15C94676 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4AE02767AC39C6230F2DC09DAFB96F5D /* Build configuration list for PBXNativeTarget "Pods-MyExperiences" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C1E41698E991715C1A1292E243573CA2 /* Debug */, + 093E2EB133C7BCE81EF107A2B0835AE3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 50EC3E189DDE4DF2306F3A862792E1FF /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8B38C0F50C50D0FA6487274AF29DBC37 /* Debug */, + 52787EF8BFB561F854D16775A1FC09BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5AC7D7BAAD2889D785E1B07169E4911C /* Build configuration list for PBXNativeTarget "FirebaseAuth" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B01CCD18817755E97B52F769301CCB3F /* Debug */, + 24C00BCC9EEF4B29987D38C1C8A260FE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5BEC0F5D4AB0F843C0076E8C32DEC47E /* Build configuration list for PBXNativeTarget "nanopb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2282AF89767243134694E4431405425F /* Debug */, + 0C1611403BD7D84AFAF332BD69336DFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 71F82A6135D33FBB3D18A38AFFE08885 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B55D9D245E017E9993D5EC86ADDD2380 /* Debug */, + 49A7DDAD23F378F1D892EA94C4F3CEF4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8D15AAFED93654EEEA494F14C576182B /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 459BAC11166CA4D3C2764E641D0CE5CD /* Debug */, + DF01653A78F4511C681F7E0431B382B2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9B149B704151435145561397AF0830FB /* Build configuration list for PBXNativeTarget "PromisesObjC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 73D98C6C7FC81825EC98891BBE55F736 /* Debug */, + B20D1D61EA67C0A56F1E7658B410D49C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9C565F1E674279068C73FA1B08B45E02 /* Build configuration list for PBXNativeTarget "FirebaseUI-FirebaseAuthUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCD49C2219A7E0938BBD502EB5B35F9A /* Debug */, + 7AC1F21D12520088001C8A71331780AA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9C971348766DBCAE0EB4E87A65E713B9 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0B27B00068AF0A536D52C438D026D833 /* Debug */, + 5A9F4D90612A2879C23028EAFF4BA473 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9FB8D339D52B52F9DAB7BA9CD4DC84FF /* Build configuration list for PBXNativeTarget "AppAuth" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3BFB49A0C652DF4A91F6D35EE641F051 /* Debug */, + CEED3BE9D9BBFC1B5BE09AA928ADAB77 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DF9B026542CE18E68EB08595D6AF5A04 /* Build configuration list for PBXNativeTarget "FirebaseUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33C224F3DF0581562DD9A9723210E4DD /* Debug */, + 27B0EB4C7A9A15F0CCC3E870C5284B83 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E89811131BF8158FC162B131E90D320F /* Build configuration list for PBXNativeTarget "FirebaseStorage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8ECBD9B9212CC23FB5D15765A5058ED0 /* Debug */, + 7BCD2751B9DFC93B2BF209BF9C529EA9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EF506430F7C768387213C9554EC30E56 /* Build configuration list for PBXAggregateTarget "GoogleSignIn" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 30A45983CA15662DA326EA1E9A9CA19F /* Debug */, + 7E8ADF207D12C725E7F8D9840D9D7F40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8730A7F30233C13704CF5AB33818D02 /* Build configuration list for PBXNativeTarget "FirebaseCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 356B259E3F15B5C01FFF2308D144D082 /* Debug */, + 0568B3BC9A7D442A26379CC12DD08AC1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F9BC9C68ACBBE046A8A6911ECF5B862B /* Build configuration list for PBXAggregateTarget "Firebase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7FC52C4287BE3F8FD34886CAD27809E4 /* Debug */, + 18D62B8ADFDFA0A86D4408A60822B89C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FF8A00C0999DC87832BE4C932BDF83FF /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8870B2195E15DA72E95A381A5CC95526 /* Debug */, + 39B585DECAB0FF087BFB93F1F90CB82D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/MyExperiences copy/Pods/PromisesObjC/LICENSE b/MyExperiences copy/Pods/PromisesObjC/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MyExperiences copy/Pods/PromisesObjC/README.md b/MyExperiences copy/Pods/PromisesObjC/README.md new file mode 100644 index 00000000..0eecbb12 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/README.md @@ -0,0 +1,60 @@ +[![Apache +License](https://img.shields.io/github/license/google/promises.svg)](LICENSE) +[![Travis](https://api.travis-ci.org/google/promises.svg?branch=master)](https://travis-ci.org/google/promises) +[![Gitter Chat](https://badges.gitter.im/google/promises.svg)](https://gitter.im/google/promises) + +![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-blue.svg?longCache=true&style=flat) +![Languages](https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg?longCache=true&style=flat) +![Package Managers](https://img.shields.io/badge/supports-Bazel%20%7C%20SwiftPM%20%7C%20CocoaPods%20%7C%20Carthage-yellow.svg?longCache=true&style=flat) + +# Promises + +Promises is a modern framework that provides a synchronization construct for +Objective-C and Swift to facilitate writing asynchronous code. + +* [Introduction](g3doc/index.md) + * [The problem with async + code](g3doc/index.md#the-problem-with-async-code) + * [Promises to the rescue](g3doc/index.md#promises-to-the-rescue) + * [What is a promise?](g3doc/index.md#what-is-a-promise) +* [Framework](g3doc/index.md#framework) + * [Features](g3doc/index.md#features) + * [Benchmark](g3doc/index.md#benchmark) +* [Getting started](g3doc/index.md#getting-started) + * [Add dependency](g3doc/index.md#add-dependency) + * [Import](g3doc/index.md#import) + * [Adopt](g3doc/index.md#adopt) +* [Basics](g3doc/index.md#basics) + * [Creating promises](g3doc/index.md#creating-promises) + * [Async](g3doc/index.md#async) + * [Do](g3doc/index.md#do) + * [Pending](g3doc/index.md#pending) + * [Resolved](g3doc/index.md#create-a-resolved-promise) + * [Observing fulfillment](g3doc/index.md#observing-fulfillment) + * [Then](g3doc/index.md#then) + * [Observing rejection](g3doc/index.md#observing-rejection) + * [Catch](g3doc/index.md#catch) +* [Extensions](g3doc/index.md#extensions) + * [All](g3doc/index.md#all) + * [Always](g3doc/index.md#always) + * [Any](g3doc/index.md#any) + * [Await](g3doc/index.md#await) + * [Delay](g3doc/index.md#delay) + * [Race](g3doc/index.md#race) + * [Recover](g3doc/index.md#recover) + * [Reduce](g3doc/index.md#reduce) + * [Retry](g3doc/index.md#retry) + * [Timeout](g3doc/index.md#timeout) + * [Validate](g3doc/index.md#validate) + * [Wrap](g3doc/index.md#wrap) +* [Advanced topics](g3doc/index.md#advanced-topics) + * [Default dispatch queue](g3doc/index.md#default-dispatch-queue) + * [Ownership and retain + cycles](g3doc/index.md#ownership-and-retain-cycles) + * [Testing](g3doc/index.md#testing) + * [Objective-C <-> Swift + interoperability](g3doc/index.md#objective-c---swift-interoperability) + * [Dot-syntax in Objective-C](g3doc/index.md#dot-syntax-in-objective-c) +* [Anti-patterns](g3doc/index.md#anti-patterns) + * [Broken chain](g3doc/index.md#broken-chain) + * [Nested promises](g3doc/index.md#nested-promises) diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m new file mode 100644 index 00000000..c21f30ef --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m @@ -0,0 +1,86 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AllAdditions) + ++ (FBLPromise *)all:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue all:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue all:(NSArray *)allPromises { + NSParameterAssert(queue); + NSParameterAssert(allPromises); + + if (allPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [allPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else if ([promise isKindOfClass:[NSError class]]) { + reject(promise); + return; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are fulfilled. + for (FBLPromise *promise in promises) { + if (!promise.isFulfilled) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill([promises valueForKey:NSStringFromSelector(@selector(value))]); + } + reject:^(NSError *error) { + reject(error); + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all { + return ^(NSArray *promises) { + return [self all:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue all:promises]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m new file mode 100644 index 00000000..69274428 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m @@ -0,0 +1,58 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Always.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AlwaysAdditions) + +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue always:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue always:(FBLPromiseAlwaysWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue + chainedFulfill:^id(id value) { + work(); + return value; + } + chainedReject:^id(NSError *error) { + work(); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AlwaysAdditions) + +- (FBLPromise * (^)(FBLPromiseAlwaysWorkBlock))always { + return ^(FBLPromiseAlwaysWorkBlock work) { + return [self always:work]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn { + return ^(dispatch_queue_t queue, FBLPromiseAlwaysWorkBlock work) { + return [self onQueue:queue always:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m new file mode 100644 index 00000000..e101c98d --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m @@ -0,0 +1,112 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Any.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +static NSArray *FBLPromiseCombineValuesAndErrors(NSArray *promises) { + NSMutableArray *combinedValuesAndErrors = [[NSMutableArray alloc] init]; + for (FBLPromise *promise in promises) { + if (promise.isFulfilled) { + [combinedValuesAndErrors addObject:promise.value ?: [NSNull null]]; + continue; + } + if (promise.isRejected) { + [combinedValuesAndErrors addObject:promise.error]; + continue; + } + assert(!promise.isPending); + }; + return combinedValuesAndErrors; +} + +@implementation FBLPromise (AnyAdditions) + ++ (FBLPromise *)any:(NSArray *)promises { + return [self onQueue:FBLPromise.defaultDispatchQueue any:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue any:(NSArray *)anyPromises { + NSParameterAssert(queue); + NSParameterAssert(anyPromises); + + if (anyPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [anyPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are resolved. + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } + reject:^(NSError *error) { + BOOL atLeastOneIsFulfilled = NO; + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + if (promise.isFulfilled) { + atLeastOneIsFulfilled = YES; + } + } + if (atLeastOneIsFulfilled) { + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } else { + reject(error); + } + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any { + return ^(NSArray *promises) { + return [self any:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue any:promises]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m new file mode 100644 index 00000000..249158ce --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m @@ -0,0 +1,70 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Async.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AsyncAdditions) + ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue async:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue async:(FBLPromiseAsyncWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + work( + ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }, + ^(NSError *error) { + [promise reject:error]; + }); + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async { + return ^(FBLPromiseAsyncWorkBlock work) { + return [self async:work]; + }; +} + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn { + return ^(dispatch_queue_t queue, FBLPromiseAsyncWorkBlock work) { + return [self onQueue:queue async:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m new file mode 100644 index 00000000..ea3b87a3 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m @@ -0,0 +1,48 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Await.h" + +#import "FBLPromisePrivate.h" + +id __nullable FBLPromiseAwait(FBLPromise *promise, NSError **outError) { + assert(promise); + + static dispatch_once_t onceToken; + static dispatch_queue_t queue; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.FBLPromises.Await", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + id __block resolution; + NSError __block *blockError; + [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + resolution = value; + dispatch_semaphore_signal(semaphore); + return value; + } + chainedReject:^id(NSError *error) { + blockError = error; + dispatch_semaphore_signal(semaphore); + return error; + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if (outError) { + *outError = blockError; + } + return resolution; +} diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m new file mode 100644 index 00000000..25e8ce63 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Catch.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (CatchAdditions) + +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject { + return [self onQueue:FBLPromise.defaultDispatchQueue catch:reject]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue catch:(FBLPromiseCatchWorkBlock)reject { + NSParameterAssert(queue); + NSParameterAssert(reject); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + reject(error); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch { + return ^(FBLPromiseCatchWorkBlock catch) { + return [self catch:catch]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn { + return ^(dispatch_queue_t queue, FBLPromiseCatchWorkBlock catch) { + return [self onQueue:queue catch:catch]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m new file mode 100644 index 00000000..ce94c336 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Delay.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DelayAdditions) + +- (FBLPromise *)delay:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue delay:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue delay:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + [promise fulfill:value]; + }); + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay { + return ^(NSTimeInterval interval) { + return [self delay:interval]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue delay:interval]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m new file mode 100644 index 00000000..eb7e10dc --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Do.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DoAdditions) + ++ (instancetype)do:(FBLPromiseDoWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue do:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DoAdditions) + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn { + return ^(dispatch_queue_t queue, FBLPromiseDoWorkBlock work) { + return [self onQueue:queue do:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m new file mode 100644 index 00000000..b5bd9f14 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m @@ -0,0 +1,65 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Race.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RaceAdditions) + ++ (instancetype)race:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue race:promises]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)racePromises { + NSParameterAssert(queue); + NSAssert(racePromises.count > 0, @"No promises to observe"); + + NSArray *promises = [racePromises copy]; + return [FBLPromise onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (id promise in promises) { + if (![promise isKindOfClass:self]) { + fulfill(promise); + return; + } + } + // Subscribe all, but only the first one to resolve will change + // the resulting promise's state. + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue fulfill:fulfill reject:reject]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race { + return ^(NSArray *promises) { + return [self race:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue race:promises]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m new file mode 100644 index 00000000..0c9326af --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Recover.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RecoverAdditions) + +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery { + return [self onQueue:FBLPromise.defaultDispatchQueue recover:recovery]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue recover:(FBLPromiseRecoverWorkBlock)recovery { + NSParameterAssert(queue); + NSParameterAssert(recovery); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + return recovery(error); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover { + return ^(FBLPromiseRecoverWorkBlock recovery) { + return [self recover:recovery]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn { + return ^(dispatch_queue_t queue, FBLPromiseRecoverWorkBlock recovery) { + return [self onQueue:queue recover:recovery]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m new file mode 100644 index 00000000..1f3fc50d --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m @@ -0,0 +1,61 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Reduce.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ReduceAdditions) + +- (FBLPromise *)reduce:(NSArray *)items combine:(FBLPromiseReducerBlock)reducer { + return [self onQueue:FBLPromise.defaultDispatchQueue reduce:items combine:reducer]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer { + NSParameterAssert(queue); + NSParameterAssert(items); + NSParameterAssert(reducer); + + FBLPromise *promise = self; + for (id item in items) { + promise = [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + return reducer(value, item); + } + chainedReject:nil]; + } + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce { + return ^(NSArray *items, FBLPromiseReducerBlock reducer) { + return [self reduce:items combine:reducer]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn { + return ^(dispatch_queue_t queue, NSArray *items, FBLPromiseReducerBlock reducer) { + return [self onQueue:queue reduce:items combine:reducer]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m new file mode 100644 index 00000000..37c55762 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m @@ -0,0 +1,128 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Retry.h" + +#import "FBLPromisePrivate.h" + +NSInteger const FBLPromiseRetryDefaultAttemptsCount = 1; +NSTimeInterval const FBLPromiseRetryDefaultDelayInterval = 1.0; + +static void FBLPromiseRetryAttempt(FBLPromise *promise, dispatch_queue_t queue, NSInteger count, + NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + __auto_type retrier = ^(id __nullable value) { + if ([value isKindOfClass:[NSError class]]) { + if (count <= 0 || (predicate && !predicate(count, value))) { + [promise reject:value]; + } else { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + FBLPromiseRetryAttempt(promise, queue, count - 1, interval, predicate, work); + }); + } + } else { + [promise fulfill:value]; + } + }; + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue fulfill:retrier reject:retrier]; + } else { + retrier(value); + } +} + +@implementation FBLPromise (RetryAdditions) + ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue attempts:FBLPromiseRetryDefaultAttemptsCount retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue attempts:count retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue + attempts:count + delay:FBLPromiseRetryDefaultDelayInterval + condition:nil + retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue + attempts:count + delay:interval + condition:predicate + retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + FBLPromiseRetryAttempt(promise, queue, count, interval, predicate, work); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry { + return ^id(FBLPromiseRetryWorkBlock work) { + return [self retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn { + return ^id(dispatch_queue_t queue, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue retry:work]; + }; +} + ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgain { + return ^id(NSInteger count, NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + return [self attempts:count delay:interval condition:predicate retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgainOn { + return ^id(dispatch_queue_t queue, NSInteger count, NSTimeInterval interval, + FBLPromiseRetryPredicateBlock predicate, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue attempts:count delay:interval condition:predicate retry:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m new file mode 100644 index 00000000..33d35368 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) { + BOOL isTimedOut = NO; + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout]; + static NSTimeInterval const minimalTimeout = 0.01; + static int64_t const minimalTimeToWait = (int64_t)(minimalTimeout * NSEC_PER_SEC); + dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, minimalTimeToWait); + dispatch_group_t dispatchGroup = FBLPromise.dispatchGroup; + NSRunLoop *runLoop = NSRunLoop.currentRunLoop; + while (dispatch_group_wait(dispatchGroup, waitTime)) { + isTimedOut = timeoutDate.timeIntervalSinceNow < 0.0; + if (isTimedOut) { + break; + } + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:minimalTimeout]]; + } + return !isTimedOut; +} + +@implementation FBLPromise (TestingAdditions) + +// These properties are implemented in the FBLPromise class itself. +@dynamic isPending; +@dynamic isFulfilled; +@dynamic isRejected; +@dynamic value; +@dynamic error; + ++ (dispatch_group_t)dispatchGroup { + static dispatch_group_t gDispatchGroup; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gDispatchGroup = dispatch_group_create(); + }); + return gDispatchGroup; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m new file mode 100644 index 00000000..ab03bd12 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m @@ -0,0 +1,50 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Then.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ThenAdditions) + +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue then:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue then:(FBLPromiseThenWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue chainedFulfill:work chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then { + return ^(FBLPromiseThenWorkBlock work) { + return [self then:work]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn { + return ^(dispatch_queue_t queue, FBLPromiseThenWorkBlock work) { + return [self onQueue:queue then:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m new file mode 100644 index 00000000..a2252e65 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m @@ -0,0 +1,64 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Timeout.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (TimeoutAdditions) + +- (FBLPromise *)timeout:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue timeout:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue timeout:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + typeof(self) __weak weakPromise = promise; + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + NSError *timedOutError = [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeTimedOut + userInfo:nil]; + [weakPromise reject:timedOutError]; + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout { + return ^(NSTimeInterval interval) { + return [self timeout:interval]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue timeout:interval]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m new file mode 100644 index 00000000..1e21e81b --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m @@ -0,0 +1,56 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Validate.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ValidateAdditions) + +- (FBLPromise*)validate:(FBLPromiseValidateWorkBlock)predicate { + return [self onQueue:FBLPromise.defaultDispatchQueue validate:predicate]; +} + +- (FBLPromise*)onQueue:(dispatch_queue_t)queue validate:(FBLPromiseValidateWorkBlock)predicate { + NSParameterAssert(queue); + NSParameterAssert(predicate); + + FBLPromiseChainedFulfillBlock chainedFulfill = ^id(id value) { + return predicate(value) ? value : + [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }; + return [self chainOnQueue:queue chainedFulfill:chainedFulfill chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ValidateAdditions) + +- (FBLPromise* (^)(FBLPromiseValidateWorkBlock))validate { + return ^(FBLPromiseValidateWorkBlock predicate) { + return [self validate:predicate]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn { + return ^(dispatch_queue_t queue, FBLPromiseValidateWorkBlock predicate) { + return [self onQueue:queue validate:predicate]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m new file mode 100644 index 00000000..3d3341eb --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m @@ -0,0 +1,420 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Wrap.h" + +#import "FBLPromise+Async.h" + +@implementation FBLPromise (WrapAdditions) + ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^{ + fulfill(nil); + }); + }]; +} + ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(id __nullable value) { + fulfill(value); + }); + }]; +} + ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(nil); + } + }); + }]; +} + ++ (instancetype)wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectOrErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (instancetype)wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorOrObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error, id __nullable value) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (FBLPromise *)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrap2ObjectsOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value1, id __nullable value2, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@[ value1, value2 ]); + } + }); + }]; +} + ++ (FBLPromise *)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(BOOL value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(BOOL value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(NSInteger value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSInteger value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:(dispatch_queue_t)queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(double value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(double value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_WrapAdditions) + ++ (FBLPromise * (^)(void (^)(FBLPromiseCompletion)))wrapCompletion { + return ^(void (^work)(FBLPromiseCompletion)) { + return [self wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseCompletion)) { + return [self onQueue:queue wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion { + return ^(void (^work)(FBLPromiseObjectCompletion)) { + return [self wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectCompletion)) { + return [self onQueue:queue wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion { + return ^(void (^work)(FBLPromiseErrorCompletion)) { + return [self wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorCompletion)) { + return [self onQueue:queue wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion { + return ^(void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self onQueue:queue wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion { + return ^(void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self onQueue:queue wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion { + return ^(void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self onQueue:queue wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion { + return ^(void (^work)(FBLPromiseBoolCompletion)) { + return [self wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolCompletion)) { + return [self onQueue:queue wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletion { + return ^(void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self onQueue:queue wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion { + return ^(void (^work)(FBLPromiseIntegerCompletion)) { + return [self wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerCompletion)) { + return [self onQueue:queue wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion { + return ^(void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self onQueue:queue wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion { + return ^(void (^work)(FBLPromiseDoubleCompletion)) { + return [self wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleCompletion)) { + return [self onQueue:queue wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion { + return ^(void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self wrapDoubleOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self onQueue:queue wrapDoubleOrErrorCompletion:work]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m new file mode 100644 index 00000000..c12ad328 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m @@ -0,0 +1,299 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromisePrivate.h" + +/** All states a promise can be in. */ +typedef NS_ENUM(NSInteger, FBLPromiseState) { + FBLPromiseStatePending = 0, + FBLPromiseStateFulfilled, + FBLPromiseStateRejected, +}; + +typedef void (^FBLPromiseObserver)(FBLPromiseState state, id __nullable resolution); + +static dispatch_queue_t gFBLPromiseDefaultDispatchQueue; + +@implementation FBLPromise { + /** Current state of the promise. */ + FBLPromiseState _state; + /** + Set of arbitrary objects to keep strongly while the promise is pending. + Becomes nil after the promise has been resolved. + */ + NSMutableSet *__nullable _pendingObjects; + /** + Value to fulfill the promise with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ + id __nullable _value; + /** + Error to reject the promise with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ + NSError *__nullable _error; + /** List of observers to notify when the promise gets resolved. */ + NSMutableArray *_observers; +} + ++ (void)initialize { + if (self == [FBLPromise class]) { + gFBLPromiseDefaultDispatchQueue = dispatch_get_main_queue(); + } +} + ++ (dispatch_queue_t)defaultDispatchQueue { + @synchronized(self) { + return gFBLPromiseDefaultDispatchQueue; + } +} + ++ (void)setDefaultDispatchQueue:(dispatch_queue_t)queue { + NSParameterAssert(queue); + + @synchronized(self) { + gFBLPromiseDefaultDispatchQueue = queue; + } +} + ++ (instancetype)pendingPromise { + return [[self alloc] initPending]; +} + ++ (instancetype)resolvedWith:(nullable id)resolution { + return [[self alloc] initWithResolution:resolution]; +} + +- (void)fulfill:(nullable id)value { + if ([value isKindOfClass:[NSError class]]) { + [self reject:(NSError *)value]; + } else { + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateFulfilled; + _value = value; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _value); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } + } +} + +- (void)reject:(NSError *)error { + NSAssert([error isKindOfClass:[NSError class]], @"Invalid error type."); + + if (![error isKindOfClass:[NSError class]]) { + // Give up on invalid error type in Release mode. + @throw error; // NOLINT + } + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateRejected; + _error = error; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _error); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } +} + +#pragma mark - NSObject + +- (NSString *)description { + if (self.isFulfilled) { + return [NSString stringWithFormat:@"<%@ %p> Fulfilled: %@", NSStringFromClass([self class]), + self, self.value]; + } + if (self.isRejected) { + return [NSString stringWithFormat:@"<%@ %p> Rejected: %@", NSStringFromClass([self class]), + self, self.error]; + } + return [NSString stringWithFormat:@"<%@ %p> Pending", NSStringFromClass([self class]), self]; +} + +#pragma mark - Private + +- (instancetype)initPending { + self = [super init]; + if (self) { + dispatch_group_enter(FBLPromise.dispatchGroup); + } + return self; +} + +- (instancetype)initWithResolution:(nullable id)resolution { + self = [super init]; + if (self) { + if ([resolution isKindOfClass:[NSError class]]) { + _state = FBLPromiseStateRejected; + _error = (NSError *)resolution; + } else { + _state = FBLPromiseStateFulfilled; + _value = resolution; + } + } + return self; +} + +- (void)dealloc { + if (_state == FBLPromiseStatePending) { + dispatch_group_leave(FBLPromise.dispatchGroup); + } +} + +- (BOOL)isPending { + @synchronized(self) { + return _state == FBLPromiseStatePending; + } +} + +- (BOOL)isFulfilled { + @synchronized(self) { + return _state == FBLPromiseStateFulfilled; + } +} + +- (BOOL)isRejected { + @synchronized(self) { + return _state == FBLPromiseStateRejected; + } +} + +- (nullable id)value { + @synchronized(self) { + return _value; + } +} + +- (NSError *__nullable)error { + @synchronized(self) { + return _error; + } +} + +- (void)addPendingObject:(id)object { + NSParameterAssert(object); + + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + if (!_pendingObjects) { + _pendingObjects = [[NSMutableSet alloc] init]; + } + [_pendingObjects addObject:object]; + } + } +} + +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject { + NSParameterAssert(queue); + NSParameterAssert(onFulfill); + NSParameterAssert(onReject); + + @synchronized(self) { + switch (_state) { + case FBLPromiseStatePending: { + if (!_observers) { + _observers = [[NSMutableArray alloc] init]; + } + [_observers addObject:^(FBLPromiseState state, id __nullable resolution) { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + switch (state) { + case FBLPromiseStatePending: + break; + case FBLPromiseStateFulfilled: + onFulfill(resolution); + break; + case FBLPromiseStateRejected: + onReject(resolution); + break; + } + }); + }]; + break; + } + case FBLPromiseStateFulfilled: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onFulfill(self->_value); + }); + break; + } + case FBLPromiseStateRejected: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onReject(self->_error); + }); + break; + } + } + } +} + +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + __auto_type resolver = ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + value = chainedFulfill ? chainedFulfill(value) : value; + resolver(value); + } + reject:^(NSError *error) { + id value = chainedReject ? chainedReject(error) : error; + resolver(value); + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntaxAdditions) + ++ (instancetype (^)(void))pending { + return ^(void) { + return [self pendingPromise]; + }; +} + ++ (instancetype (^)(id __nullable))resolved { + return ^(id resolution) { + return [self resolvedWith:resolution]; + }; +} + +@end diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m new file mode 100644 index 00000000..1cc181ad --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m @@ -0,0 +1,19 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NSErrorDomain const FBLPromiseErrorDomain = @"com.google.FBLPromises.Error"; diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h new file mode 100644 index 00000000..9c0090e2 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AllAdditions) + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)all:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected FBLPromise correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + all:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `all` operators. + Usage: FBLPromise.all(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h new file mode 100644 index 00000000..13000f5b --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AlwaysAdditions) + +typedef void (^FBLPromiseAlwaysWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to dispatch on. + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + always:(FBLPromiseAlwaysWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `always` operators. + Usage: promise.always(^{...}) + */ +@interface FBLPromise(DotSyntax_AlwaysAdditions) + +- (FBLPromise* (^)(FBLPromiseAlwaysWorkBlock))always FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h new file mode 100644 index 00000000..82875bf7 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h @@ -0,0 +1,69 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AnyAdditions) + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSErrors`, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)any:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSError`s, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + any:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `any` operators. + Usage: FBLPromise.any(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h new file mode 100644 index 00000000..0588a9ea --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AsyncAdditions) + +typedef void (^FBLPromiseFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseAsyncWorkBlock)(FBLPromiseFulfillBlock fulfill, + FBLPromiseRejectBlock reject) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + async:(FBLPromiseAsyncWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `async` operators. + Usage: FBLPromise.async(^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { ... }) + */ +@interface FBLPromise(DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h new file mode 100644 index 00000000..c97a1baf --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for promise resolution. The current thread blocks until the promise is resolved. + + @param promise Promise to wait for. + @param error Error the promise was rejected with, or `nil` if the promise was fulfilled. + @return Value the promise was fulfilled with. If the promise was rejected, the return value + is always `nil`, but the error out arg is not. + */ +FOUNDATION_EXTERN id __nullable FBLPromiseAwait(FBLPromise *promise, + NSError **error) NS_REFINED_FOR_SWIFT; + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h new file mode 100644 index 00000000..a9ff170f --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(CatchAdditions) + +typedef void (^FBLPromiseCatchWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously. + + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously on the given queue. + + @param queue A queue to invoke the `reject` block on. + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + catch:(FBLPromiseCatchWorkBlock)reject NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `catch` operators. + Usage: promise.catch(^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h new file mode 100644 index 00000000..557df485 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DelayAdditions) + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)delay:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + delay:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `delay` operators. + Usage: promise.delay(...) + */ +@interface FBLPromise(DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h new file mode 100644 index 00000000..6838e0ad --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DoAdditions) + +typedef id __nullable (^FBLPromiseDoWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)do:(FBLPromiseDoWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `do` operators. + Usage: FBLPromise.doOn(queue, ^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_DoAdditions) + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h new file mode 100644 index 00000000..2f67258d --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h @@ -0,0 +1,62 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RaceAdditions) + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)race:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `race` operators. + Usage: FBLPromise.race(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h new file mode 100644 index 00000000..bb7df7ec --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RecoverAdditions) + +typedef id __nullable (^FBLPromiseRecoverWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param queue A queue to dispatch on. + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + recover:(FBLPromiseRecoverWorkBlock)recovery NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `recover` operators. + Usage: promise.recover(^id(NSError *error) {...}) + */ +@interface FBLPromise(DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h new file mode 100644 index 00000000..5bb1eeee --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h @@ -0,0 +1,71 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ReduceAdditions) + +typedef id __nullable (^FBLPromiseReducerBlock)(Value __nullable partial, id next) + NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param queue A queue to dispatch on. + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `reduce` operators. + Usage: promise.reduce(values, ^id(id partial, id next) { ... }) + */ +@interface FBLPromise(DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h new file mode 100644 index 00000000..98ef558c --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h @@ -0,0 +1,165 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** The default number of retry attempts is 1. */ +FOUNDATION_EXTERN NSInteger const FBLPromiseRetryDefaultAttemptsCount NS_REFINED_FOR_SWIFT; + +/** The default delay interval before making a retry attempt is 1.0 second. */ +FOUNDATION_EXTERN NSTimeInterval const FBLPromiseRetryDefaultDelayInterval NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(RetryAdditions) + +typedef id __nullable (^FBLPromiseRetryWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); +typedef BOOL (^FBLPromiseRetryPredicateBlock)(NSInteger, NSError *) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on rejection where the + `work` block is retried after a delay of `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on + rejection where the `work` block is retried on the given `queue` after a delay of + `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param queue A queue to invoke the `work` block on. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. On rejection, the `work` block is retried after the given delay `interval` and will + continue to retry until the number of specified attempts have been exhausted or will bail early if + the given condition is not met. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. On rejection, the `work` block is retried after the given + delay `interval` and will continue to retry until the number of specified attempts have been + exhausted or will bail early if the given condition is not met. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise+Retry` operators. + Usage: FBLPromise.retry(^id { ... }) + */ +@interface FBLPromise(DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgain FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, + FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgainOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h new file mode 100644 index 00000000..8478ae22 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h @@ -0,0 +1,57 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for all scheduled promises blocks. + + @param timeout Maximum time to wait. + @return YES if all promises blocks have completed before the timeout and NO otherwise. + */ +FOUNDATION_EXTERN BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(TestingAdditions) + +/** + Dispatch group for promises that is typically used to wait for all scheduled blocks. + */ +@property(class, nonatomic, readonly) dispatch_group_t dispatchGroup NS_REFINED_FOR_SWIFT; + +/** + Properties to get the current state of the promise. + */ +@property(nonatomic, readonly) BOOL isPending NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isFulfilled NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isRejected NS_REFINED_FOR_SWIFT; + +/** + Value the promise was fulfilled with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ +@property(nonatomic, readonly, nullable) Value value NS_REFINED_FOR_SWIFT; + +/** + Error the promise was rejected with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ +@property(nonatomic, readonly, nullable) NSError *error NS_REFINED_FOR_SWIFT; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h new file mode 100644 index 00000000..32027e69 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ThenAdditions) + +typedef id __nullable (^FBLPromiseThenWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously only + when the receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with + the same error. + + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously when the + receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with the same + error. + + @param queue A queue to invoke the `work` block on. + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + then:(FBLPromiseThenWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `then` operators. + Usage: promise.then(^id(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h new file mode 100644 index 00000000..184ba166 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h @@ -0,0 +1,57 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(TimeoutAdditions) + +/** + Waits for a promise with the specified `timeout`. + + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)timeout:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Waits for a promise with the specified `timeout`. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + timeout:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `timeout` operators. + Usage: promise.timeout(...) + */ +@interface FBLPromise(DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h new file mode 100644 index 00000000..9dfa2f16 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ValidateAdditions) + +typedef BOOL (^FBLPromiseValidateWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)validate:(FBLPromiseValidateWorkBlock)predicate NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param queue A queue to dispatch on. + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + validate:(FBLPromiseValidateWorkBlock)predicate NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `validate` operators. + Usage: promise.validate(^BOOL(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ValidateAdditions) + +- (FBLPromise * (^)(FBLPromiseValidateWorkBlock))validate FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h new file mode 100644 index 00000000..664e1bbf --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h @@ -0,0 +1,316 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Different types of completion handlers available to be wrapped with promise. + */ +typedef void (^FBLPromiseCompletion)(void) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectCompletion)(id __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorCompletion)(NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectOrErrorCompletion)(id __nullable, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorOrObjectCompletion)(NSError* __nullable, id __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromise2ObjectsOrErrorCompletion)(id __nullable, id __nullable, + NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolCompletion)(BOOL) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolOrErrorCompletion)(BOOL, NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerCompletion)(NSInteger) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerOrErrorCompletion)(NSInteger, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleCompletion)(double) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleOrErrorCompletion)(double, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); + +/** + Provides an easy way to convert methods that use common callback patterns into promises. + */ +@interface FBLPromise(WrapAdditions) + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)wrapObjectOrErrorCompletion: + (void (^)(FBLPromiseObjectOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)wrapErrorOrObjectCompletion: + (void (^)(FBLPromiseErrorOrObjectCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `wrap` operators. + Usage: FBLPromise.wrapCompletion(^(FBLPromiseCompletion handler) {...}) + */ +@interface FBLPromise(DotSyntax_WrapAdditions) + ++ (FBLPromise* (^)(void (^)(FBLPromiseCompletion)))wrapCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h new file mode 100644 index 00000000..b1380dc7 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h @@ -0,0 +1,93 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Promises synchronization construct in Objective-C. + */ +@interface FBLPromise<__covariant Value> : NSObject + +/** + Default dispatch queue used for `FBLPromise`, which is `main` if a queue is not specified. + */ +@property(class) dispatch_queue_t defaultDispatchQueue NS_REFINED_FOR_SWIFT; + +/** + Creates a pending promise. + */ ++ (instancetype)pendingPromise NS_REFINED_FOR_SWIFT; + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ ++ (instancetype)resolvedWith:(nullable id)resolution NS_REFINED_FOR_SWIFT; + +/** + Synchronously fulfills the promise with a value. + + @param value An arbitrary value to fulfill the promise with, including `nil`. + */ +- (void)fulfill:(nullable Value)value NS_REFINED_FOR_SWIFT; + +/** + Synchronously rejects the promise with an error. + + @param error An error to reject the promise with. + */ +- (void)reject:(NSError *)error NS_REFINED_FOR_SWIFT; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; +@end + +@interface FBLPromise() + +/** + Adds an object to the set of pending objects to keep strongly while the promise is pending. + Used by the Swift wrappers to keep them alive until the underlying ObjC promise is resolved. + + @param object An object to add. + */ +- (void)addPendingObject:(id)object NS_REFINED_FOR_SWIFT; + +@end + +#ifdef FBL_PROMISES_DOT_SYNTAX_IS_DEPRECATED +#define FBL_PROMISES_DOT_SYNTAX __attribute__((deprecated)) +#else +#define FBL_PROMISES_DOT_SYNTAX +#endif + +@interface FBLPromise(DotSyntaxAdditions) + +/** + Convenience dot-syntax wrappers for FBLPromise. + Usage: FBLPromise.pending() + FBLPromise.resolved(value) + + */ ++ (instancetype (^)(void))pending FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (instancetype (^)(id __nullable))resolved FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h new file mode 100644 index 00000000..d37af536 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h @@ -0,0 +1,43 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXTERN NSErrorDomain const FBLPromiseErrorDomain NS_REFINED_FOR_SWIFT; + +/** + Possible error codes in `FBLPromiseErrorDomain`. + */ +typedef NS_ENUM(NSInteger, FBLPromiseErrorCode) { + /** Promise failed to resolve in time. */ + FBLPromiseErrorCodeTimedOut = 1, + /** Validation predicate returned false. */ + FBLPromiseErrorCodeValidationFailure = 2, +} NS_REFINED_FOR_SWIFT; + +NS_INLINE BOOL FBLPromiseErrorIsTimedOut(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeTimedOut; +} + +NS_INLINE BOOL FBLPromiseErrorIsValidationFailure(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeValidationFailure; +} + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h new file mode 100644 index 00000000..7a132f20 --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h @@ -0,0 +1,66 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Miscellaneous low-level private interfaces available to extend standard FBLPromise functionality. + */ +@interface FBLPromise() + +typedef void (^FBLPromiseOnFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseOnRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedFulfillBlock)(Value __nullable value) + NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedRejectBlock)(NSError *error) + NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise. + */ +- (instancetype)initPending NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ +- (instancetype)initWithResolution:(nullable id)resolution NS_SWIFT_UNAVAILABLE(""); + +/** + Invokes `fulfill` and `reject` blocks on `queue` when the receiver gets either fulfilled or + rejected respectively. + */ +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject NS_SWIFT_UNAVAILABLE(""); + +/** + Returns a new promise which gets resolved with the return value of `chainedFulfill` or + `chainedReject` blocks respectively. The blocks are invoked when the receiver gets either + fulfilled or rejected. If `nil` is passed to either block arg, the returned promise is resolved + with the same resolution as the receiver. + */ +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h new file mode 100644 index 00000000..2d90badb --- /dev/null +++ b/MyExperiences copy/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-Info.plist b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-Info.plist new file mode 100644 index 00000000..7b6b52a4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-dummy.m b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-dummy.m new file mode 100644 index 00000000..0f45668e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_AppAuth : NSObject +@end +@implementation PodsDummy_AppAuth +@end diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-prefix.pch b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-umbrella.h b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-umbrella.h new file mode 100644 index 00000000..7e9c5909 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth-umbrella.h @@ -0,0 +1,84 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "AppAuthCore.h" +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDAuthorizationService.h" +#import "OIDAuthState.h" +#import "OIDAuthStateChangeDelegate.h" +#import "OIDAuthStateErrorDelegate.h" +#import "OIDClientMetadataParameters.h" +#import "OIDDefines.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" +#import "OIDError.h" +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" +#import "OIDExternalUserAgentRequest.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDFieldMapping.h" +#import "OIDGrantTypes.h" +#import "OIDIDToken.h" +#import "OIDRegistrationRequest.h" +#import "OIDRegistrationResponse.h" +#import "OIDResponseTypes.h" +#import "OIDScopes.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDTokenUtilities.h" +#import "OIDURLQueryComponent.h" +#import "OIDURLSessionProvider.h" +#import "AppAuth.h" +#import "AppAuthCore.h" +#import "OIDAuthorizationRequest.h" +#import "OIDAuthorizationResponse.h" +#import "OIDAuthorizationService.h" +#import "OIDAuthState.h" +#import "OIDAuthStateChangeDelegate.h" +#import "OIDAuthStateErrorDelegate.h" +#import "OIDClientMetadataParameters.h" +#import "OIDDefines.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" +#import "OIDError.h" +#import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" +#import "OIDExternalUserAgentRequest.h" +#import "OIDExternalUserAgentSession.h" +#import "OIDFieldMapping.h" +#import "OIDGrantTypes.h" +#import "OIDIDToken.h" +#import "OIDRegistrationRequest.h" +#import "OIDRegistrationResponse.h" +#import "OIDResponseTypes.h" +#import "OIDScopes.h" +#import "OIDScopeUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDTokenRequest.h" +#import "OIDTokenResponse.h" +#import "OIDTokenUtilities.h" +#import "OIDURLQueryComponent.h" +#import "OIDURLSessionProvider.h" +#import "OIDAuthorizationService+IOS.h" +#import "OIDAuthState+IOS.h" +#import "OIDExternalUserAgentCatalyst.h" +#import "OIDExternalUserAgentIOS.h" +#import "OIDExternalUserAgentIOSCustomBrowser.h" + +FOUNDATION_EXPORT double AppAuthVersionNumber; +FOUNDATION_EXPORT const unsigned char AppAuthVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.debug.xcconfig new file mode 100644 index 00000000..47199e55 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppAuth +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "SafariServices" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.modulemap b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.modulemap new file mode 100644 index 00000000..9299d0a3 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.modulemap @@ -0,0 +1,6 @@ +framework module AppAuth { + umbrella header "AppAuth-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.release.xcconfig new file mode 100644 index 00000000..47199e55 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/AppAuth/AppAuth.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppAuth +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "SafariServices" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig new file mode 100644 index 00000000..c775a304 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.release.xcconfig new file mode 100644 index 00000000..c775a304 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Firebase/Firebase.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig new file mode 100644 index 00000000..af966ec0 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig new file mode 100644 index 00000000..af966ec0 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-Info.plist new file mode 100644 index 00000000..3fe24c0a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.6.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-dummy.m new file mode 100644 index 00000000..63dc4593 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseAuth : NSObject +@end +@implementation PodsDummy_FirebaseAuth +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-umbrella.h new file mode 100644 index 00000000..445c530c --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth-umbrella.h @@ -0,0 +1,50 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRActionCodeSettings.h" +#import "FIRAdditionalUserInfo.h" +#import "FIRAuth.h" +#import "FIRAuthAPNSTokenType.h" +#import "FIRAuthCredential.h" +#import "FIRAuthDataResult.h" +#import "FIRAuthErrors.h" +#import "FIRAuthSettings.h" +#import "FIRAuthTokenResult.h" +#import "FIRAuthUIDelegate.h" +#import "FirebaseAuth.h" +#import "FirebaseAuthVersion.h" +#import "FIREmailAuthProvider.h" +#import "FIRFacebookAuthProvider.h" +#import "FIRFederatedAuthProvider.h" +#import "FIRGameCenterAuthProvider.h" +#import "FIRGitHubAuthProvider.h" +#import "FIRGoogleAuthProvider.h" +#import "FIRMultiFactor.h" +#import "FIRMultiFactorAssertion.h" +#import "FIRMultiFactorInfo.h" +#import "FIRMultiFactorResolver.h" +#import "FIRMultiFactorSession.h" +#import "FIROAuthCredential.h" +#import "FIROAuthProvider.h" +#import "FIRPhoneAuthCredential.h" +#import "FIRPhoneAuthProvider.h" +#import "FIRPhoneMultiFactorAssertion.h" +#import "FIRPhoneMultiFactorGenerator.h" +#import "FIRPhoneMultiFactorInfo.h" +#import "FIRTwitterAuthProvider.h" +#import "FIRUser.h" +#import "FIRUserInfo.h" +#import "FIRUserMetadata.h" + +FOUNDATION_EXPORT double FirebaseAuthVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseAuthVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.debug.xcconfig new file mode 100644 index 00000000..1fe8f9cb --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRAuth_VERSION=6.6.0 FIRAuth_MINOR_VERSION=6.6 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.modulemap new file mode 100644 index 00000000..7ee6c707 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseAuth { + umbrella header "FirebaseAuth-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.release.xcconfig new file mode 100644 index 00000000..1fe8f9cb --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseAuth/FirebaseAuth.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRAuth_VERSION=6.6.0 FIRAuth_MINOR_VERSION=6.6 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist new file mode 100644 index 00000000..24cdb413 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.8.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m new file mode 100644 index 00000000..4f1eb273 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCore : NSObject +@end +@implementation PodsDummy_FirebaseCore +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h new file mode 100644 index 00000000..102aecb8 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FirebaseCore.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" + +FOUNDATION_EXPORT double FirebaseCoreVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig new file mode 100644 index 00000000..6907dcf3 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.8.0 Firebase_VERSION=6.27.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap new file mode 100644 index 00000000..4c38b871 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCore { + umbrella header "FirebaseCore-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig new file mode 100644 index 00000000..6907dcf3 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.8.0 Firebase_VERSION=6.27.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist new file mode 100644 index 00000000..7b6b52a4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m new file mode 100644 index 00000000..224d263e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCoreDiagnostics : NSObject +@end +@implementation PodsDummy_FirebaseCoreDiagnostics +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h new file mode 100644 index 00000000..11dc6599 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "firebasecore.nanopb.h" +#import "FIRCoreDiagnosticsData.h" +#import "FIRCoreDiagnosticsInterop.h" + +FOUNDATION_EXPORT double FirebaseCoreDiagnosticsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreDiagnosticsVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig new file mode 100644 index 00000000..fcfb7aa3 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap new file mode 100644 index 00000000..d9cad8bc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCoreDiagnostics { + umbrella header "FirebaseCoreDiagnostics-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig new file mode 100644 index 00000000..fcfb7aa3 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist new file mode 100644 index 00000000..64061506 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.3.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m new file mode 100644 index 00000000..40813e77 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseDatabase : NSObject +@end +@implementation PodsDummy_FirebaseDatabase +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h new file mode 100644 index 00000000..b9b40ff2 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h @@ -0,0 +1,25 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FirebaseDatabase.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +FOUNDATION_EXPORT double FirebaseDatabaseVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseDatabaseVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig new file mode 100644 index 00000000..147035fb --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.3.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap new file mode 100644 index 00000000..7424a952 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseDatabase { + umbrella header "FirebaseDatabase-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig new file mode 100644 index 00000000..147035fb --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.3.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist new file mode 100644 index 00000000..7b6b52a4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m new file mode 100644 index 00000000..ae19551a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstallations : NSObject +@end +@implementation PodsDummy_FirebaseInstallations +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h new file mode 100644 index 00000000..78e59795 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstallations.h" +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" + +FOUNDATION_EXPORT double FirebaseInstallationsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstallationsVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig new file mode 100644 index 00000000..14bc5046 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.4.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap new file mode 100644 index 00000000..f6e2a295 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstallations { + umbrella header "FirebaseInstallations-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig new file mode 100644 index 00000000..14bc5046 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.4.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist new file mode 100644 index 00000000..3ef6a8d4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.7.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m new file mode 100644 index 00000000..15945eed --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseStorage : NSObject +@end +@implementation PodsDummy_FirebaseStorage +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h new file mode 100644 index 00000000..40d61443 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h @@ -0,0 +1,27 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseStorage.h" +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageObservableTask.h" +#import "FIRStorageReference.h" +#import "FIRStorageTask.h" +#import "FIRStorageTaskSnapshot.h" +#import "FIRStorageUploadTask.h" + +FOUNDATION_EXPORT double FirebaseStorageVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseStorageVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.debug.xcconfig new file mode 100644 index 00000000..7c17eeb0 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRStorage_VERSION=3.7.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseStorage +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap new file mode 100644 index 00000000..627ff18b --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseStorage { + umbrella header "FirebaseStorage-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.release.xcconfig new file mode 100644 index 00000000..7c17eeb0 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRStorage_VERSION=3.7.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseStorage +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-Info.plist new file mode 100644 index 00000000..bb325f3d --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 8.4.2 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-dummy.m b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-dummy.m new file mode 100644 index 00000000..28eebca5 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseUI : NSObject +@end +@implementation PodsDummy_FirebaseUI +@end diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-prefix.pch b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-umbrella.h b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-umbrella.h new file mode 100644 index 00000000..d59b307f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI-umbrella.h @@ -0,0 +1,34 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FUIAccountSettingsOperationType.h" +#import "FUIAccountSettingsViewController.h" +#import "FirebaseAuthUI.h" +#import "FUIAuth.h" +#import "FUIAuth_Internal.h" +#import "FUIAuthBaseViewController.h" +#import "FUIAuthBaseViewController_Internal.h" +#import "FUIAuthErrors.h" +#import "FUIAuthErrorUtils.h" +#import "FUIAuthPickerViewController.h" +#import "FUIAuthProvider.h" +#import "FUIAuthUtils.h" +#import "FUIAuthStrings.h" +#import "FUIPrivacyAndTermsOfServiceView.h" +#import "FUIAuthTableViewCell.h" +#import "FUIAuthTableHeaderView.h" +#import "FirebaseGoogleAuthUI.h" +#import "FUIGoogleAuth.h" + +FOUNDATION_EXPORT double FirebaseUIVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseUIVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.debug.xcconfig new file mode 100644 index 00000000..8f49d722 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" $(PODS_ROOT)/FirebaseUI/FirebaseAuthUI $(PODS_ROOT)/FirebaseUI/FirebaseGoogleAuthUI +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseUI +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.modulemap b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.modulemap new file mode 100644 index 00000000..284eea67 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseUI { + umbrella header "FirebaseUI-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.release.xcconfig new file mode 100644 index 00000000..8f49d722 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/FirebaseUI.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" $(PODS_ROOT)/FirebaseUI/FirebaseAuthUI $(PODS_ROOT)/FirebaseUI/FirebaseGoogleAuthUI +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseUI +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist new file mode 100644 index 00000000..6f811fde --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseAuthUI-FirebaseUI-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 8.4.2 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist new file mode 100644 index 00000000..6f811fde --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/FirebaseUI/ResourceBundle-FirebaseGoogleAuthUI-FirebaseUI-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 8.4.2 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-Info.plist b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-dummy.m b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-dummy.m new file mode 100644 index 00000000..04b91f31 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GTMAppAuth : NSObject +@end +@implementation PodsDummy_GTMAppAuth +@end diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-prefix.pch b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-umbrella.h b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-umbrella.h new file mode 100644 index 00000000..4ab5f86a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GTMAppAuth.h" +#import "GTMAppAuthFetcherAuthorization+Keychain.h" +#import "GTMAppAuthFetcherAuthorization.h" +#import "GTMKeychain.h" +#import "GTMOAuth2KeychainCompatibility.h" + +FOUNDATION_EXPORT double GTMAppAuthVersionNumber; +FOUNDATION_EXPORT const unsigned char GTMAppAuthVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.debug.xcconfig new file mode 100644 index 00000000..217cc41a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "SafariServices" -framework "Security" -framework "SystemConfiguration" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GTMAppAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.modulemap b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.modulemap new file mode 100644 index 00000000..b23c8d07 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.modulemap @@ -0,0 +1,6 @@ +framework module GTMAppAuth { + umbrella header "GTMAppAuth-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.release.xcconfig new file mode 100644 index 00000000..217cc41a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMAppAuth/GTMAppAuth.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "SafariServices" -framework "Security" -framework "SystemConfiguration" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GTMAppAuth +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist new file mode 100644 index 00000000..7b6b52a4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m new file mode 100644 index 00000000..13d68b3f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GTMSessionFetcher : NSObject +@end +@implementation PodsDummy_GTMSessionFetcher +@end diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h new file mode 100644 index 00000000..b9e0b3de --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h @@ -0,0 +1,23 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GTMSessionFetcher.h" +#import "GTMSessionFetcherLogging.h" +#import "GTMSessionFetcherService.h" +#import "GTMSessionUploadFetcher.h" +#import "GTMGatherInputStream.h" +#import "GTMMIMEDocument.h" +#import "GTMReadMonitorInputStream.h" + +FOUNDATION_EXPORT double GTMSessionFetcherVersionNumber; +FOUNDATION_EXPORT const unsigned char GTMSessionFetcherVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.debug.xcconfig new file mode 100644 index 00000000..af4ab71f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "Security" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GTMSessionFetcher +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap new file mode 100644 index 00000000..5121a4dc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap @@ -0,0 +1,6 @@ +framework module GTMSessionFetcher { + umbrella header "GTMSessionFetcher-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.release.xcconfig new file mode 100644 index 00000000..af4ab71f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "Security" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GTMSessionFetcher +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig new file mode 100644 index 00000000..7a8ce57a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig new file mode 100644 index 00000000..7a8ce57a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist new file mode 100644 index 00000000..7e52625a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.2.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m new file mode 100644 index 00000000..9a08ec35 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransport : NSObject +@end +@implementation PodsDummy_GoogleDataTransport +@end diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h new file mode 100644 index 00000000..eb436e1e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h @@ -0,0 +1,33 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GDTCORAssert.h" +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPlatform.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORReachability.h" +#import "GDTCORRegistrar.h" +#import "GDTCORStorageProtocol.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploader.h" +#import "GDTCORUploadPackage.h" +#import "GoogleDataTransport.h" + +FOUNDATION_EXPORT double GoogleDataTransportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig new file mode 100644 index 00000000..9eb91b6e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=6.2.1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap new file mode 100644 index 00000000..8a67414a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransport { + umbrella header "GoogleDataTransport-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig new file mode 100644 index 00000000..9eb91b6e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=6.2.1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist new file mode 100644 index 00000000..9ae03a0c --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m new file mode 100644 index 00000000..3c7f5569 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransportCCTSupport : NSObject +@end +@implementation PodsDummy_GoogleDataTransportCCTSupport +@end diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h new file mode 100644 index 00000000..f17d9d86 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GDTCOREvent+GDTCCTSupport.h" + +FOUNDATION_EXPORT double GoogleDataTransportCCTSupportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportCCTSupportVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig new file mode 100644 index 00000000..ede445cd --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=3.2.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap new file mode 100644 index 00000000..7cec8f02 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransportCCTSupport { + umbrella header "GoogleDataTransportCCTSupport-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig new file mode 100644 index 00000000..ede445cd --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=3.2.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.debug.xcconfig new file mode 100644 index 00000000..889b0187 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleSignIn +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "Foundation" -framework "LocalAuthentication" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleSignIn +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.release.xcconfig new file mode 100644 index 00000000..889b0187 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleSignIn/GoogleSignIn.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleSignIn +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "CoreGraphics" -framework "CoreText" -framework "Foundation" -framework "LocalAuthentication" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleSignIn +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist new file mode 100644 index 00000000..3fe24c0a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.6.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m new file mode 100644 index 00000000..98ac4e95 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleUtilities : NSObject +@end +@implementation PodsDummy_GoogleUtilities +@end diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h new file mode 100644 index 00000000..508e6310 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GULLoggerLevel.h" +#import "GULLoggerCodes.h" +#import "GULNSData+zlib.h" + +FOUNDATION_EXPORT double GoogleUtilitiesVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleUtilitiesVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig new file mode 100644 index 00000000..07b83c7f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap new file mode 100644 index 00000000..491dd0a1 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap @@ -0,0 +1,6 @@ +framework module GoogleUtilities { + umbrella header "GoogleUtilities-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig new file mode 100644 index 00000000..07b83c7f --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-Info.plist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.markdown b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.markdown new file mode 100644 index 00000000..5c2700bc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.markdown @@ -0,0 +1,3205 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## AppAuth + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## Firebase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseAnalytics + +Copyright 2020 Google + +## FirebaseAuth + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnostics + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseDatabase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstallations + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseStorage + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseUI + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GTMAppAuth + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GTMSessionFetcher + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2020 Google + +## GoogleDataTransport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleDataTransportCCTSupport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleSignIn + +Copyright 2019 Google + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog + + +## PromisesObjC + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## leveldb-library + +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Generated by CocoaPods - https://cocoapods.org diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.plist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.plist new file mode 100644 index 00000000..8fa997ae --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-acknowledgements.plist @@ -0,0 +1,3351 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache License, Version 2.0 + Title + AppAuth + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAuth + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnostics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseDatabase + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstallations + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseStorage + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache 2.0 + Title + FirebaseUI + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache License, Version 2.0 + Title + GTMAppAuth + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GTMSessionFetcher + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransportCCTSupport + Type + PSGroupSpecifier + + + FooterText + Copyright 2019 Google + License + Copyright + Title + GoogleSignIn + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller <landon@landonf.org> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +<a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev Wiki +Crack Prevention</a>: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at <a href="http://landonf.org/2009/02/index.html">Landon +Fuller's blog</a> + + License + Apache + Title + GoogleUtilities + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + PromisesObjC + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + New BSD + Title + leveldb-library + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-dummy.m b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-dummy.m new file mode 100644 index 00000000..3a23c171 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_MyExperiences : NSObject +@end +@implementation PodsDummy_Pods_MyExperiences +@end diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-input-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 00000000..14f5b4bd --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,8 @@ +${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh +${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework +${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework +${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-output-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 00000000..12ddfe92 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,7 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-input-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-input-files.xcfilelist new file mode 100644 index 00000000..14f5b4bd --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,8 @@ +${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh +${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework +${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework +${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-output-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-output-files.xcfilelist new file mode 100644 index 00000000..12ddfe92 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,7 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh new file mode 100755 index 00000000..33d4085c --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-frameworks.sh @@ -0,0 +1,219 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +install_artifact() { + artifact="$1" + base="$(basename "$artifact")" + case $base in + *.framework) + install_framework "$artifact" + ;; + *.dSYM) + # Suppress arch warnings since XCFrameworks will include many dSYM files + install_dsym "$artifact" "false" + ;; + *.bcsymbolmap) + install_bcsymbolmap "$artifact" + ;; + *) + echo "error: Unrecognized artifact "$artifact"" + ;; + esac +} + +copy_artifacts() { + file_list="$1" + while read artifact; do + install_artifact "$artifact" + done <$file_list +} + +ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" +if [ -r "${ARTIFACT_LIST_FILE}" ]; then + copy_artifacts "${ARTIFACT_LIST_FILE}" +fi + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-input-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-input-files.xcfilelist new file mode 100644 index 00000000..3bbd3bf8 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-input-files.xcfilelist @@ -0,0 +1,4 @@ +${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh +${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseAuthUI.bundle +${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseGoogleAuthUI.bundle +${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-output-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-output-files.xcfilelist new file mode 100644 index 00000000..49f71cfc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Debug-output-files.xcfilelist @@ -0,0 +1,3 @@ +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseAuthUI.bundle +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseGoogleAuthUI.bundle +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-input-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-input-files.xcfilelist new file mode 100644 index 00000000..3bbd3bf8 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-input-files.xcfilelist @@ -0,0 +1,4 @@ +${PODS_ROOT}/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh +${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseAuthUI.bundle +${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseGoogleAuthUI.bundle +${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-output-files.xcfilelist b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-output-files.xcfilelist new file mode 100644 index 00000000..49f71cfc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources-Release-output-files.xcfilelist @@ -0,0 +1,3 @@ +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseAuthUI.bundle +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseGoogleAuthUI.bundle +${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle \ No newline at end of file diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh new file mode 100755 index 00000000..16de71a0 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-resources.sh @@ -0,0 +1,133 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseAuthUI.bundle" + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseGoogleAuthUI.bundle" + install_resource "${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseAuthUI.bundle" + install_resource "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseGoogleAuthUI.bundle" + install_resource "${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle" +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find -L "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" + fi +fi diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-umbrella.h b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-umbrella.h new file mode 100644 index 00000000..1020b757 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_MyExperiencesVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_MyExperiencesVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.debug.xcconfig new file mode 100644 index 00000000..4428df7a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth/AppAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage/FirebaseStorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseUI.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth/GTMAppAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources $(PODS_ROOT)/FirebaseUI/FirebaseAuthUI $(PODS_ROOT)/FirebaseUI/FirebaseGoogleAuthUI "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "AppAuth" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreTelephony" -framework "CoreText" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseStorage" -framework "FirebaseUI" -framework "Foundation" -framework "GTMAppAuth" -framework "GTMSessionFetcher" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleSignIn" -framework "GoogleUtilities" -framework "LocalAuthentication" -framework "MobileCoreServices" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.modulemap b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.modulemap new file mode 100644 index 00000000..ee993c81 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.modulemap @@ -0,0 +1,6 @@ +framework module Pods_MyExperiences { + umbrella header "Pods-MyExperiences-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.release.xcconfig new file mode 100644 index 00000000..4428df7a --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/Pods-MyExperiences/Pods-MyExperiences.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" "${PODS_ROOT}/GoogleSignIn/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AppAuth/AppAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuth/FirebaseAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage/FirebaseStorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseUI/FirebaseUI.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMAppAuth/GTMAppAuth.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources $(PODS_ROOT)/FirebaseUI/FirebaseAuthUI $(PODS_ROOT)/FirebaseUI/FirebaseGoogleAuthUI "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "AppAuth" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreTelephony" -framework "CoreText" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseAuth" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseStorage" -framework "FirebaseUI" -framework "Foundation" -framework "GTMAppAuth" -framework "GTMSessionFetcher" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleSignIn" -framework "GoogleUtilities" -framework "LocalAuthentication" -framework "MobileCoreServices" -framework "SafariServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" -weak_framework "AuthenticationServices" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist new file mode 100644 index 00000000..57e52a19 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.9 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m new file mode 100644 index 00000000..ab1f2104 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PromisesObjC : NSObject +@end +@implementation PodsDummy_PromisesObjC +@end diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h new file mode 100644 index 00000000..5b014a8b --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h @@ -0,0 +1,36 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Testing.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" +#import "FBLPromise.h" +#import "FBLPromiseError.h" +#import "FBLPromises.h" + +FOUNDATION_EXPORT double FBLPromisesVersionNumber; +FOUNDATION_EXPORT const unsigned char FBLPromisesVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig new file mode 100644 index 00000000..dac127e6 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap new file mode 100644 index 00000000..7d485cdc --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap @@ -0,0 +1,6 @@ +framework module FBLPromises { + umbrella header "PromisesObjC-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig new file mode 100644 index 00000000..dac127e6 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist new file mode 100644 index 00000000..da1bc00d --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.22.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m new file mode 100644 index 00000000..dba14922 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_leveldb_library : NSObject +@end +@implementation PodsDummy_leveldb_library +@end diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h new file mode 100644 index 00000000..6a459026 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h @@ -0,0 +1,31 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "c.h" +#import "cache.h" +#import "comparator.h" +#import "db.h" +#import "dumpfile.h" +#import "env.h" +#import "export.h" +#import "filter_policy.h" +#import "iterator.h" +#import "options.h" +#import "slice.h" +#import "status.h" +#import "table.h" +#import "table_builder.h" +#import "write_batch.h" + +FOUNDATION_EXPORT double leveldbVersionNumber; +FOUNDATION_EXPORT const unsigned char leveldbVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig new file mode 100644 index 00000000..d1992a19 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap new file mode 100644 index 00000000..fd77435c --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap @@ -0,0 +1,6 @@ +framework module leveldb { + umbrella header "leveldb-library-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig new file mode 100644 index 00000000..d1992a19 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-Info.plist b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-Info.plist new file mode 100644 index 00000000..aaca2d5c --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.30905.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-dummy.m b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-dummy.m new file mode 100644 index 00000000..b3fa5956 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_nanopb : NSObject +@end +@implementation PodsDummy_nanopb +@end diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-prefix.pch b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-umbrella.h b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-umbrella.h new file mode 100644 index 00000000..07e77b38 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "pb.h" +#import "pb_common.h" +#import "pb_decode.h" +#import "pb_encode.h" +#import "pb.h" +#import "pb_decode.h" +#import "pb_common.h" +#import "pb.h" +#import "pb_encode.h" +#import "pb_common.h" + +FOUNDATION_EXPORT double nanopbVersionNumber; +FOUNDATION_EXPORT const unsigned char nanopbVersionString[]; + diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig new file mode 100644 index 00000000..8e7193b4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.modulemap b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.modulemap new file mode 100644 index 00000000..e8d4b532 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.modulemap @@ -0,0 +1,6 @@ +framework module nanopb { + umbrella header "nanopb-umbrella.h" + + export * + module * { export * } +} diff --git a/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.release.xcconfig b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.release.xcconfig new file mode 100644 index 00000000..8e7193b4 --- /dev/null +++ b/MyExperiences copy/Pods/Target Support Files/nanopb/nanopb.release.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/MyExperiences copy/Pods/leveldb-library/LICENSE b/MyExperiences copy/Pods/leveldb-library/LICENSE new file mode 100644 index 00000000..8e80208c --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MyExperiences copy/Pods/leveldb-library/README.md b/MyExperiences copy/Pods/leveldb-library/README.md new file mode 100644 index 00000000..0b660aee --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/README.md @@ -0,0 +1,225 @@ +**LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.** + +[![Build Status](https://travis-ci.org/google/leveldb.svg?branch=master)](https://travis-ci.org/google/leveldb) +[![Build status](https://ci.appveyor.com/api/projects/status/g2j5j4rfkda6eyw5/branch/master?svg=true)](https://ci.appveyor.com/project/pwnall/leveldb) + +Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) + +# Features + + * Keys and values are arbitrary byte arrays. + * Data is stored sorted by key. + * Callers can provide a custom comparison function to override the sort order. + * The basic operations are `Put(key,value)`, `Get(key)`, `Delete(key)`. + * Multiple changes can be made in one atomic batch. + * Users can create a transient snapshot to get a consistent view of data. + * Forward and backward iteration is supported over the data. + * Data is automatically compressed using the [Snappy compression library](http://google.github.io/snappy/). + * External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions. + +# Documentation + + [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code. + +# Limitations + + * This is not a SQL database. It does not have a relational data model, it does not support SQL queries, and it has no support for indexes. + * Only a single process (possibly multi-threaded) can access a particular database at a time. + * There is no client-server support builtin to the library. An application that needs such support will have to wrap their own server around the library. + +# Building + +This project supports [CMake](https://cmake.org/) out of the box. + +### Build for POSIX + +Quick start: + +```bash +mkdir -p build && cd build +cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . +``` + +### Building for Windows + +First generate the Visual Studio 2017 project/solution files: + +```cmd +mkdir build +cd build +cmake -G "Visual Studio 15" .. +``` +The default default will build for x86. For 64-bit run: + +```cmd +cmake -G "Visual Studio 15 Win64" .. +``` + +To compile the Windows solution from the command-line: + +```cmd +devenv /build Debug leveldb.sln +``` + +or open leveldb.sln in Visual Studio and build from within. + +Please see the CMake documentation and `CMakeLists.txt` for more advanced usage. + +# Contributing to the leveldb Project + +The leveldb project welcomes contributions. leveldb's primary goal is to be +a reliable and fast key/value store. Changes that are in line with the +features/limitations outlined above, and meet the requirements below, +will be considered. + +Contribution requirements: + +1. **Tested platforms only**. We _generally_ will only accept changes for + platforms that are compiled and tested. This means POSIX (for Linux and + macOS) or Windows. Very small changes will sometimes be accepted, but + consider that more of an exception than the rule. + +2. **Stable API**. We strive very hard to maintain a stable API. Changes that + require changes for projects using leveldb _might_ be rejected without + sufficient benefit to the project. + +3. **Tests**: All changes must be accompanied by a new (or changed) test, or + a sufficient explanation as to why a new (or changed) test is not required. + +4. **Consistent Style**: This project conforms to the + [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html). + To ensure your changes are properly formatted please run: + + ``` + clang-format -i --style=file + ``` + +## Submitting a Pull Request + +Before any pull request will be accepted the author must first sign a +Contributor License Agreement (CLA) at https://cla.developers.google.com/. + +In order to keep the commit timeline linear +[squash](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Squashing-Commits) +your changes down to a single commit and [rebase](https://git-scm.com/docs/git-rebase) +on google/leveldb/master. This keeps the commit timeline linear and more easily sync'ed +with the internal repository at Google. More information at GitHub's +[About Git rebase](https://help.github.com/articles/about-git-rebase/) page. + +# Performance + +Here is a performance report (with explanations) from the run of the +included db_bench program. The results are somewhat noisy, but should +be enough to get a ballpark performance estimate. + +## Setup + +We use a database with a million entries. Each entry has a 16 byte +key, and a 100 byte value. Values used by the benchmark compress to +about half their original size. + + LevelDB: version 1.1 + Date: Sun May 1 12:11:26 2011 + CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz + CPUCache: 4096 KB + Keys: 16 bytes each + Values: 100 bytes each (50 bytes after compression) + Entries: 1000000 + Raw Size: 110.6 MB (estimated) + File Size: 62.9 MB (estimated) + +## Write performance + +The "fill" benchmarks create a brand new database, in either +sequential, or random order. The "fillsync" benchmark flushes data +from the operating system to the disk after every operation; the other +write operations leave the data sitting in the operating system buffer +cache for a while. The "overwrite" benchmark does random writes that +update existing keys in the database. + + fillseq : 1.765 micros/op; 62.7 MB/s + fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops) + fillrandom : 2.460 micros/op; 45.0 MB/s + overwrite : 2.380 micros/op; 46.5 MB/s + +Each "op" above corresponds to a write of a single key/value pair. +I.e., a random write benchmark goes at approximately 400,000 writes per second. + +Each "fillsync" operation costs much less (0.3 millisecond) +than a disk seek (typically 10 milliseconds). We suspect that this is +because the hard disk itself is buffering the update in its memory and +responding before the data has been written to the platter. This may +or may not be safe based on whether or not the hard disk has enough +power to save its memory in the event of a power failure. + +## Read performance + +We list the performance of reading sequentially in both the forward +and reverse direction, and also the performance of a random lookup. +Note that the database created by the benchmark is quite small. +Therefore the report characterizes the performance of leveldb when the +working set fits in memory. The cost of reading a piece of data that +is not present in the operating system buffer cache will be dominated +by the one or two disk seeks needed to fetch the data from disk. +Write performance will be mostly unaffected by whether or not the +working set fits in memory. + + readrandom : 16.677 micros/op; (approximately 60,000 reads per second) + readseq : 0.476 micros/op; 232.3 MB/s + readreverse : 0.724 micros/op; 152.9 MB/s + +LevelDB compacts its underlying storage data in the background to +improve read performance. The results listed above were done +immediately after a lot of random writes. The results after +compactions (which are usually triggered automatically) are better. + + readrandom : 11.602 micros/op; (approximately 85,000 reads per second) + readseq : 0.423 micros/op; 261.8 MB/s + readreverse : 0.663 micros/op; 166.9 MB/s + +Some of the high cost of reads comes from repeated decompression of blocks +read from disk. If we supply enough cache to the leveldb so it can hold the +uncompressed blocks in memory, the read performance improves again: + + readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) + readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) + +## Repository contents + +See [doc/index.md](doc/index.md) for more explanation. See +[doc/impl.md](doc/impl.md) for a brief overview of the implementation. + +The public interface is in include/*.h. Callers should not include or +rely on the details of any other header files in this package. Those +internal APIs may be changed without warning. + +Guide to header files: + +* **include/db.h**: Main interface to the DB: Start here + +* **include/options.h**: Control over the behavior of an entire database, +and also control over the behavior of individual reads and writes. + +* **include/comparator.h**: Abstraction for user-specified comparison function. +If you want just bytewise comparison of keys, you can use the default +comparator, but clients can write their own comparator implementations if they +want custom ordering (e.g. to handle different character encodings, etc.) + +* **include/iterator.h**: Interface for iterating over data. You can get +an iterator from a DB object. + +* **include/write_batch.h**: Interface for atomically applying multiple +updates to a database. + +* **include/slice.h**: A simple module for maintaining a pointer and a +length into some other byte array. + +* **include/status.h**: Status is returned from many of the public interfaces +and is used to report success and various kinds of errors. + +* **include/env.h**: +Abstraction of the OS environment. A posix implementation of this interface is +in util/env_posix.cc + +* **include/table.h, include/table_builder.h**: Lower-level modules that most +clients probably won't use directly diff --git a/MyExperiences copy/Pods/leveldb-library/db/builder.cc b/MyExperiences copy/Pods/leveldb-library/db/builder.cc new file mode 100644 index 00000000..9520ee45 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/builder.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/builder.h" + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta) { + Status s; + meta->file_size = 0; + iter->SeekToFirst(); + + std::string fname = TableFileName(dbname, meta->number); + if (iter->Valid()) { + WritableFile* file; + s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + + TableBuilder* builder = new TableBuilder(options, file); + meta->smallest.DecodeFrom(iter->key()); + for (; iter->Valid(); iter->Next()) { + Slice key = iter->key(); + meta->largest.DecodeFrom(key); + builder->Add(key, iter->value()); + } + + // Finish and check for builder errors + s = builder->Finish(); + if (s.ok()) { + meta->file_size = builder->FileSize(); + assert(meta->file_size > 0); + } + delete builder; + + // Finish and check for file errors + if (s.ok()) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (s.ok()) { + // Verify that the table is usable + Iterator* it = table_cache->NewIterator(ReadOptions(), meta->number, + meta->file_size); + s = it->status(); + delete it; + } + } + + // Check for input iterator errors + if (!iter->status().ok()) { + s = iter->status(); + } + + if (s.ok() && meta->file_size > 0) { + // Keep it + } else { + env->DeleteFile(fname); + } + return s; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/builder.h b/MyExperiences copy/Pods/leveldb-library/db/builder.h new file mode 100644 index 00000000..7bd0b804 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/builder.h @@ -0,0 +1,30 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ +#define STORAGE_LEVELDB_DB_BUILDER_H_ + +#include "leveldb/status.h" + +namespace leveldb { + +struct Options; +struct FileMetaData; + +class Env; +class Iterator; +class TableCache; +class VersionEdit; + +// Build a Table file from the contents of *iter. The generated file +// will be named according to meta->number. On success, the rest of +// *meta will be filled with metadata about the generated table. +// If no data is present in *iter, meta->file_size will be set to +// zero, and no Table file will be produced. +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/c.cc b/MyExperiences copy/Pods/leveldb-library/db/c.cc new file mode 100644 index 00000000..e0f3367d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/c.cc @@ -0,0 +1,566 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/c.h" + +#include + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::FilterPolicy; +using leveldb::Iterator; +using leveldb::kMajorVersion; +using leveldb::kMinorVersion; +using leveldb::Logger; +using leveldb::NewBloomFilterPolicy; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; + +extern "C" { + +struct leveldb_t { + DB* rep; +}; +struct leveldb_iterator_t { + Iterator* rep; +}; +struct leveldb_writebatch_t { + WriteBatch rep; +}; +struct leveldb_snapshot_t { + const Snapshot* rep; +}; +struct leveldb_readoptions_t { + ReadOptions rep; +}; +struct leveldb_writeoptions_t { + WriteOptions rep; +}; +struct leveldb_options_t { + Options rep; +}; +struct leveldb_cache_t { + Cache* rep; +}; +struct leveldb_seqfile_t { + SequentialFile* rep; +}; +struct leveldb_randomfile_t { + RandomAccessFile* rep; +}; +struct leveldb_writablefile_t { + WritableFile* rep; +}; +struct leveldb_logger_t { + Logger* rep; +}; +struct leveldb_filelock_t { + FileLock* rep; +}; + +struct leveldb_comparator_t : public Comparator { + virtual ~leveldb_comparator_t() { (*destructor_)(state_); } + + virtual int Compare(const Slice& a, const Slice& b) const { + return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); + } + + virtual const char* Name() const { return (*name_)(state_); } + + // No-ops since the C binding does not support key shortening methods. + virtual void FindShortestSeparator(std::string*, const Slice&) const {} + virtual void FindShortSuccessor(std::string* key) const {} + + void* state_; + void (*destructor_)(void*); + int (*compare_)(void*, const char* a, size_t alen, const char* b, + size_t blen); + const char* (*name_)(void*); +}; + +struct leveldb_filterpolicy_t : public FilterPolicy { + virtual ~leveldb_filterpolicy_t() { (*destructor_)(state_); } + + virtual const char* Name() const { return (*name_)(state_); } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + std::vector key_pointers(n); + std::vector key_sizes(n); + for (int i = 0; i < n; i++) { + key_pointers[i] = keys[i].data(); + key_sizes[i] = keys[i].size(); + } + size_t len; + char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); + dst->append(filter, len); + free(filter); + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return (*key_match_)(state_, key.data(), key.size(), filter.data(), + filter.size()); + } + + void* state_; + void (*destructor_)(void*); + const char* (*name_)(void*); + char* (*create_)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length); + unsigned char (*key_match_)(void*, const char* key, size_t length, + const char* filter, size_t filter_length); +}; + +struct leveldb_env_t { + Env* rep; + bool is_default; +}; + +static bool SaveError(char** errptr, const Status& s) { + assert(errptr != nullptr); + if (s.ok()) { + return false; + } else if (*errptr == nullptr) { + *errptr = strdup(s.ToString().c_str()); + } else { + // TODO(sanjay): Merge with existing error? + free(*errptr); + *errptr = strdup(s.ToString().c_str()); + } + return true; +} + +static char* CopyString(const std::string& str) { + char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); + memcpy(result, str.data(), sizeof(char) * str.size()); + return result; +} + +leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name, + char** errptr) { + DB* db; + if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { + return nullptr; + } + leveldb_t* result = new leveldb_t; + result->rep = db; + return result; +} + +void leveldb_close(leveldb_t* db) { + delete db->rep; + delete db; +} + +void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, + db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); +} + +void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); +} + +void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr) { + SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); +} + +char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr) { + char* result = nullptr; + std::string tmp; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + } else { + *vallen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options) { + leveldb_iterator_t* result = new leveldb_iterator_t; + result->rep = db->rep->NewIterator(options->rep); + return result; +} + +const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db) { + leveldb_snapshot_t* result = new leveldb_snapshot_t; + result->rep = db->rep->GetSnapshot(); + return result; +} + +void leveldb_release_snapshot(leveldb_t* db, + const leveldb_snapshot_t* snapshot) { + db->rep->ReleaseSnapshot(snapshot->rep); + delete snapshot; +} + +char* leveldb_property_value(leveldb_t* db, const char* propname) { + std::string tmp; + if (db->rep->GetProperty(Slice(propname), &tmp)) { + // We use strdup() since we expect human readable output. + return strdup(tmp.c_str()); + } else { + return nullptr; + } +} + +void leveldb_approximate_sizes(leveldb_t* db, int num_ranges, + const char* const* range_start_key, + const size_t* range_start_key_len, + const char* const* range_limit_key, + const size_t* range_limit_key_len, + uint64_t* sizes) { + Range* ranges = new Range[num_ranges]; + for (int i = 0; i < num_ranges; i++) { + ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); + ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); + } + db->rep->GetApproximateSizes(ranges, num_ranges, sizes); + delete[] ranges; +} + +void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, const char* limit_key, + size_t limit_key_len) { + Slice a, b; + db->rep->CompactRange( + // Pass null Slice if corresponding "const char*" is null + (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr), + (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr)); +} + +void leveldb_destroy_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, DestroyDB(name, options->rep)); +} + +void leveldb_repair_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, RepairDB(name, options->rep)); +} + +void leveldb_iter_destroy(leveldb_iterator_t* iter) { + delete iter->rep; + delete iter; +} + +unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { + return iter->rep->Valid(); +} + +void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { + iter->rep->SeekToFirst(); +} + +void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { + iter->rep->SeekToLast(); +} + +void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { + iter->rep->Seek(Slice(k, klen)); +} + +void leveldb_iter_next(leveldb_iterator_t* iter) { iter->rep->Next(); } + +void leveldb_iter_prev(leveldb_iterator_t* iter) { iter->rep->Prev(); } + +const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { + Slice s = iter->rep->key(); + *klen = s.size(); + return s.data(); +} + +const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { + Slice s = iter->rep->value(); + *vlen = s.size(); + return s.data(); +} + +void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { + SaveError(errptr, iter->rep->status()); +} + +leveldb_writebatch_t* leveldb_writebatch_create() { + return new leveldb_writebatch_t; +} + +void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { delete b; } + +void leveldb_writebatch_clear(leveldb_writebatch_t* b) { b->rep.Clear(); } + +void leveldb_writebatch_put(leveldb_writebatch_t* b, const char* key, + size_t klen, const char* val, size_t vlen) { + b->rep.Put(Slice(key, klen), Slice(val, vlen)); +} + +void leveldb_writebatch_delete(leveldb_writebatch_t* b, const char* key, + size_t klen) { + b->rep.Delete(Slice(key, klen)); +} + +void leveldb_writebatch_iterate(const leveldb_writebatch_t* b, void* state, + void (*put)(void*, const char* k, size_t klen, + const char* v, size_t vlen), + void (*deleted)(void*, const char* k, + size_t klen)) { + class H : public WriteBatch::Handler { + public: + void* state_; + void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); + void (*deleted_)(void*, const char* k, size_t klen); + virtual void Put(const Slice& key, const Slice& value) { + (*put_)(state_, key.data(), key.size(), value.data(), value.size()); + } + virtual void Delete(const Slice& key) { + (*deleted_)(state_, key.data(), key.size()); + } + }; + H handler; + handler.state_ = state; + handler.put_ = put; + handler.deleted_ = deleted; + b->rep.Iterate(&handler); +} + +void leveldb_writebatch_append(leveldb_writebatch_t* destination, + const leveldb_writebatch_t* source) { + destination->rep.Append(source->rep); +} + +leveldb_options_t* leveldb_options_create() { return new leveldb_options_t; } + +void leveldb_options_destroy(leveldb_options_t* options) { delete options; } + +void leveldb_options_set_comparator(leveldb_options_t* opt, + leveldb_comparator_t* cmp) { + opt->rep.comparator = cmp; +} + +void leveldb_options_set_filter_policy(leveldb_options_t* opt, + leveldb_filterpolicy_t* policy) { + opt->rep.filter_policy = policy; +} + +void leveldb_options_set_create_if_missing(leveldb_options_t* opt, + unsigned char v) { + opt->rep.create_if_missing = v; +} + +void leveldb_options_set_error_if_exists(leveldb_options_t* opt, + unsigned char v) { + opt->rep.error_if_exists = v; +} + +void leveldb_options_set_paranoid_checks(leveldb_options_t* opt, + unsigned char v) { + opt->rep.paranoid_checks = v; +} + +void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { + opt->rep.env = (env ? env->rep : nullptr); +} + +void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { + opt->rep.info_log = (l ? l->rep : nullptr); +} + +void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { + opt->rep.write_buffer_size = s; +} + +void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { + opt->rep.max_open_files = n; +} + +void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { + opt->rep.block_cache = c->rep; +} + +void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { + opt->rep.block_size = s; +} + +void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { + opt->rep.block_restart_interval = n; +} + +void leveldb_options_set_max_file_size(leveldb_options_t* opt, size_t s) { + opt->rep.max_file_size = s; +} + +void leveldb_options_set_compression(leveldb_options_t* opt, int t) { + opt->rep.compression = static_cast(t); +} + +leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)) { + leveldb_comparator_t* result = new leveldb_comparator_t; + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->name_ = name; + return result; +} + +void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { delete cmp; } + +leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)) { + leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; + result->state_ = state; + result->destructor_ = destructor; + result->create_ = create_filter; + result->key_match_ = key_may_match; + result->name_ = name; + return result; +} + +void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { + delete filter; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { + // Make a leveldb_filterpolicy_t, but override all of its methods so + // they delegate to a NewBloomFilterPolicy() instead of user + // supplied C functions. + struct Wrapper : public leveldb_filterpolicy_t { + static void DoNothing(void*) {} + + ~Wrapper() { delete rep_; } + const char* Name() const { return rep_->Name(); } + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + return rep_->CreateFilter(keys, n, dst); + } + bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return rep_->KeyMayMatch(key, filter); + } + + const FilterPolicy* rep_; + }; + Wrapper* wrapper = new Wrapper; + wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); + wrapper->state_ = nullptr; + wrapper->destructor_ = &Wrapper::DoNothing; + return wrapper; +} + +leveldb_readoptions_t* leveldb_readoptions_create() { + return new leveldb_readoptions_t; +} + +void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { delete opt; } + +void leveldb_readoptions_set_verify_checksums(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.verify_checksums = v; +} + +void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.fill_cache = v; +} + +void leveldb_readoptions_set_snapshot(leveldb_readoptions_t* opt, + const leveldb_snapshot_t* snap) { + opt->rep.snapshot = (snap ? snap->rep : nullptr); +} + +leveldb_writeoptions_t* leveldb_writeoptions_create() { + return new leveldb_writeoptions_t; +} + +void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { delete opt; } + +void leveldb_writeoptions_set_sync(leveldb_writeoptions_t* opt, + unsigned char v) { + opt->rep.sync = v; +} + +leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { + leveldb_cache_t* c = new leveldb_cache_t; + c->rep = NewLRUCache(capacity); + return c; +} + +void leveldb_cache_destroy(leveldb_cache_t* cache) { + delete cache->rep; + delete cache; +} + +leveldb_env_t* leveldb_create_default_env() { + leveldb_env_t* result = new leveldb_env_t; + result->rep = Env::Default(); + result->is_default = true; + return result; +} + +void leveldb_env_destroy(leveldb_env_t* env) { + if (!env->is_default) delete env->rep; + delete env; +} + +char* leveldb_env_get_test_directory(leveldb_env_t* env) { + std::string result; + if (!env->rep->GetTestDirectory(&result).ok()) { + return nullptr; + } + + char* buffer = static_cast(malloc(result.size() + 1)); + memcpy(buffer, result.data(), result.size()); + buffer[result.size()] = '\0'; + return buffer; +} + +void leveldb_free(void* ptr) { free(ptr); } + +int leveldb_major_version() { return kMajorVersion; } + +int leveldb_minor_version() { return kMinorVersion; } + +} // end extern "C" diff --git a/MyExperiences copy/Pods/leveldb-library/db/db_impl.cc b/MyExperiences copy/Pods/leveldb-library/db/db_impl.cc new file mode 100644 index 00000000..761ebf6f --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/db_impl.cc @@ -0,0 +1,1550 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "db/builder.h" +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/mutexlock.h" + +namespace leveldb { + +const int kNumNonTableCacheFiles = 10; + +// Information kept for every waiting writer +struct DBImpl::Writer { + explicit Writer(port::Mutex* mu) + : batch(nullptr), sync(false), done(false), cv(mu) {} + + Status status; + WriteBatch* batch; + bool sync; + bool done; + port::CondVar cv; +}; + +struct DBImpl::CompactionState { + // Files produced by compaction + struct Output { + uint64_t number; + uint64_t file_size; + InternalKey smallest, largest; + }; + + Output* current_output() { return &outputs[outputs.size() - 1]; } + + explicit CompactionState(Compaction* c) + : compaction(c), + smallest_snapshot(0), + outfile(nullptr), + builder(nullptr), + total_bytes(0) {} + + Compaction* const compaction; + + // Sequence numbers < smallest_snapshot are not significant since we + // will never have to service a snapshot below smallest_snapshot. + // Therefore if we have seen a sequence number S <= smallest_snapshot, + // we can drop all entries for the same key with sequence numbers < S. + SequenceNumber smallest_snapshot; + + std::vector outputs; + + // State kept for output being generated + WritableFile* outfile; + TableBuilder* builder; + + uint64_t total_bytes; +}; + +// Fix user-supplied options to be reasonable +template +static void ClipToRange(T* ptr, V minvalue, V maxvalue) { + if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; + if (static_cast(*ptr) < minvalue) *ptr = minvalue; +} +Options SanitizeOptions(const std::string& dbname, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src) { + Options result = src; + result.comparator = icmp; + result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr; + ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); + ClipToRange(&result.write_buffer_size, 64 << 10, 1 << 30); + ClipToRange(&result.max_file_size, 1 << 20, 1 << 30); + ClipToRange(&result.block_size, 1 << 10, 4 << 20); + if (result.info_log == nullptr) { + // Open a log file in the same directory as the db + src.env->CreateDir(dbname); // In case it does not exist + src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname)); + Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log); + if (!s.ok()) { + // No place suitable for logging + result.info_log = nullptr; + } + } + if (result.block_cache == nullptr) { + result.block_cache = NewLRUCache(8 << 20); + } + return result; +} + +static int TableCacheSize(const Options& sanitized_options) { + // Reserve ten files or so for other uses and give the rest to TableCache. + return sanitized_options.max_open_files - kNumNonTableCacheFiles; +} + +DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) + : env_(raw_options.env), + internal_comparator_(raw_options.comparator), + internal_filter_policy_(raw_options.filter_policy), + options_(SanitizeOptions(dbname, &internal_comparator_, + &internal_filter_policy_, raw_options)), + owns_info_log_(options_.info_log != raw_options.info_log), + owns_cache_(options_.block_cache != raw_options.block_cache), + dbname_(dbname), + table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))), + db_lock_(nullptr), + shutting_down_(false), + background_work_finished_signal_(&mutex_), + mem_(nullptr), + imm_(nullptr), + has_imm_(false), + logfile_(nullptr), + logfile_number_(0), + log_(nullptr), + seed_(0), + tmp_batch_(new WriteBatch), + background_compaction_scheduled_(false), + manual_compaction_(nullptr), + versions_(new VersionSet(dbname_, &options_, table_cache_, + &internal_comparator_)) {} + +DBImpl::~DBImpl() { + // Wait for background work to finish. + mutex_.Lock(); + shutting_down_.store(true, std::memory_order_release); + while (background_compaction_scheduled_) { + background_work_finished_signal_.Wait(); + } + mutex_.Unlock(); + + if (db_lock_ != nullptr) { + env_->UnlockFile(db_lock_); + } + + delete versions_; + if (mem_ != nullptr) mem_->Unref(); + if (imm_ != nullptr) imm_->Unref(); + delete tmp_batch_; + delete log_; + delete logfile_; + delete table_cache_; + + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } +} + +Status DBImpl::NewDB() { + VersionEdit new_db; + new_db.SetComparatorName(user_comparator()->Name()); + new_db.SetLogNumber(0); + new_db.SetNextFile(2); + new_db.SetLastSequence(0); + + const std::string manifest = DescriptorFileName(dbname_, 1); + WritableFile* file; + Status s = env_->NewWritableFile(manifest, &file); + if (!s.ok()) { + return s; + } + { + log::Writer log(file); + std::string record; + new_db.EncodeTo(&record); + s = log.AddRecord(record); + if (s.ok()) { + s = file->Close(); + } + } + delete file; + if (s.ok()) { + // Make "CURRENT" file that points to the new manifest file. + s = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(manifest); + } + return s; +} + +void DBImpl::MaybeIgnoreError(Status* s) const { + if (s->ok() || options_.paranoid_checks) { + // No change needed + } else { + Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); + *s = Status::OK(); + } +} + +void DBImpl::DeleteObsoleteFiles() { + mutex_.AssertHeld(); + + if (!bg_error_.ok()) { + // After a background error, we don't know whether a new version may + // or may not have been committed, so we cannot safely garbage collect. + return; + } + + // Make a set of all of the live files + std::set live = pending_outputs_; + versions_->AddLiveFiles(&live); + + std::vector filenames; + env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + bool keep = true; + switch (type) { + case kLogFile: + keep = ((number >= versions_->LogNumber()) || + (number == versions_->PrevLogNumber())); + break; + case kDescriptorFile: + // Keep my manifest file, and any newer incarnations' + // (in case there is a race that allows other incarnations) + keep = (number >= versions_->ManifestFileNumber()); + break; + case kTableFile: + keep = (live.find(number) != live.end()); + break; + case kTempFile: + // Any temp files that are currently being written to must + // be recorded in pending_outputs_, which is inserted into "live" + keep = (live.find(number) != live.end()); + break; + case kCurrentFile: + case kDBLockFile: + case kInfoLogFile: + keep = true; + break; + } + + if (!keep) { + if (type == kTableFile) { + table_cache_->Evict(number); + } + Log(options_.info_log, "Delete type=%d #%lld\n", static_cast(type), + static_cast(number)); + env_->DeleteFile(dbname_ + "/" + filenames[i]); + } + } + } +} + +Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) { + mutex_.AssertHeld(); + + // Ignore error from CreateDir since the creation of the DB is + // committed only when the descriptor is created, and this directory + // may already exist from a previous failed creation attempt. + env_->CreateDir(dbname_); + assert(db_lock_ == nullptr); + Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); + if (!s.ok()) { + return s; + } + + if (!env_->FileExists(CurrentFileName(dbname_))) { + if (options_.create_if_missing) { + s = NewDB(); + if (!s.ok()) { + return s; + } + } else { + return Status::InvalidArgument( + dbname_, "does not exist (create_if_missing is false)"); + } + } else { + if (options_.error_if_exists) { + return Status::InvalidArgument(dbname_, + "exists (error_if_exists is true)"); + } + } + + s = versions_->Recover(save_manifest); + if (!s.ok()) { + return s; + } + SequenceNumber max_sequence(0); + + // Recover from all newer log files than the ones named in the + // descriptor (new log files may have been added by the previous + // incarnation without registering them in the descriptor). + // + // Note that PrevLogNumber() is no longer used, but we pay + // attention to it in case we are recovering a database + // produced by an older version of leveldb. + const uint64_t min_log = versions_->LogNumber(); + const uint64_t prev_log = versions_->PrevLogNumber(); + std::vector filenames; + s = env_->GetChildren(dbname_, &filenames); + if (!s.ok()) { + return s; + } + std::set expected; + versions_->AddLiveFiles(&expected); + uint64_t number; + FileType type; + std::vector logs; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + expected.erase(number); + if (type == kLogFile && ((number >= min_log) || (number == prev_log))) + logs.push_back(number); + } + } + if (!expected.empty()) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d missing files; e.g.", + static_cast(expected.size())); + return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin()))); + } + + // Recover in the order in which the logs were generated + std::sort(logs.begin(), logs.end()); + for (size_t i = 0; i < logs.size(); i++) { + s = RecoverLogFile(logs[i], (i == logs.size() - 1), save_manifest, edit, + &max_sequence); + if (!s.ok()) { + return s; + } + + // The previous incarnation may not have written any MANIFEST + // records after allocating this log number. So we manually + // update the file number allocation counter in VersionSet. + versions_->MarkFileNumberUsed(logs[i]); + } + + if (versions_->LastSequence() < max_sequence) { + versions_->SetLastSequence(max_sequence); + } + + return Status::OK(); +} + +Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log, + bool* save_manifest, VersionEdit* edit, + SequenceNumber* max_sequence) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // null if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == nullptr ? "(ignoring error) " : ""), fname, + static_cast(bytes), s.ToString().c_str()); + if (this->status != nullptr && this->status->ok()) *this->status = s; + } + }; + + mutex_.AssertHeld(); + + // Open the log file + std::string fname = LogFileName(dbname_, log_number); + SequentialFile* file; + Status status = env_->NewSequentialFile(fname, &file); + if (!status.ok()) { + MaybeIgnoreError(&status); + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : nullptr); + // We intentionally make log::Reader do checksumming even if + // paranoid_checks==false so that corruptions cause entire commits + // to be skipped instead of propagating bad information (like overly + // large sequence numbers). + log::Reader reader(file, &reporter, true /*checksum*/, 0 /*initial_offset*/); + Log(options_.info_log, "Recovering log #%llu", + (unsigned long long)log_number); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + int compactions = 0; + MemTable* mem = nullptr; + while (reader.ReadRecord(&record, &scratch) && status.ok()) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + + if (mem == nullptr) { + mem = new MemTable(internal_comparator_); + mem->Ref(); + } + status = WriteBatchInternal::InsertInto(&batch, mem); + MaybeIgnoreError(&status); + if (!status.ok()) { + break; + } + const SequenceNumber last_seq = WriteBatchInternal::Sequence(&batch) + + WriteBatchInternal::Count(&batch) - 1; + if (last_seq > *max_sequence) { + *max_sequence = last_seq; + } + + if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) { + compactions++; + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + mem->Unref(); + mem = nullptr; + if (!status.ok()) { + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + break; + } + } + } + + delete file; + + // See if we should keep reusing the last log file. + if (status.ok() && options_.reuse_logs && last_log && compactions == 0) { + assert(logfile_ == nullptr); + assert(log_ == nullptr); + assert(mem_ == nullptr); + uint64_t lfile_size; + if (env_->GetFileSize(fname, &lfile_size).ok() && + env_->NewAppendableFile(fname, &logfile_).ok()) { + Log(options_.info_log, "Reusing old log %s \n", fname.c_str()); + log_ = new log::Writer(logfile_, lfile_size); + logfile_number_ = log_number; + if (mem != nullptr) { + mem_ = mem; + mem = nullptr; + } else { + // mem can be nullptr if lognum exists but was empty. + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + } + } + } + + if (mem != nullptr) { + // mem did not get reused; compact it. + if (status.ok()) { + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + } + mem->Unref(); + } + + return status; +} + +Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, + Version* base) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + Log(options_.info_log, "Level-0 table #%llu: started", + (unsigned long long)meta.number); + + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + mutex_.Lock(); + } + + Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", + (unsigned long long)meta.number, (unsigned long long)meta.file_size, + s.ToString().c_str()); + delete iter; + pending_outputs_.erase(meta.number); + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + const Slice min_user_key = meta.smallest.user_key(); + const Slice max_user_key = meta.largest.user_key(); + if (base != nullptr) { + level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); + } + edit->AddFile(level, meta.number, meta.file_size, meta.smallest, + meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats_[level].Add(stats); + return s; +} + +void DBImpl::CompactMemTable() { + mutex_.AssertHeld(); + assert(imm_ != nullptr); + + // Save the contents of the memtable as a new Table + VersionEdit edit; + Version* base = versions_->current(); + base->Ref(); + Status s = WriteLevel0Table(imm_, &edit, base); + base->Unref(); + + if (s.ok() && shutting_down_.load(std::memory_order_acquire)) { + s = Status::IOError("Deleting DB during memtable compaction"); + } + + // Replace immutable memtable with the generated Table + if (s.ok()) { + edit.SetPrevLogNumber(0); + edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed + s = versions_->LogAndApply(&edit, &mutex_); + } + + if (s.ok()) { + // Commit to the new state + imm_->Unref(); + imm_ = nullptr; + has_imm_.store(false, std::memory_order_release); + DeleteObsoleteFiles(); + } else { + RecordBackgroundError(s); + } +} + +void DBImpl::CompactRange(const Slice* begin, const Slice* end) { + int max_level_with_files = 1; + { + MutexLock l(&mutex_); + Version* base = versions_->current(); + for (int level = 1; level < config::kNumLevels; level++) { + if (base->OverlapInLevel(level, begin, end)) { + max_level_with_files = level; + } + } + } + TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap + for (int level = 0; level < max_level_with_files; level++) { + TEST_CompactRange(level, begin, end); + } +} + +void DBImpl::TEST_CompactRange(int level, const Slice* begin, + const Slice* end) { + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + + InternalKey begin_storage, end_storage; + + ManualCompaction manual; + manual.level = level; + manual.done = false; + if (begin == nullptr) { + manual.begin = nullptr; + } else { + begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); + manual.begin = &begin_storage; + } + if (end == nullptr) { + manual.end = nullptr; + } else { + end_storage = InternalKey(*end, 0, static_cast(0)); + manual.end = &end_storage; + } + + MutexLock l(&mutex_); + while (!manual.done && !shutting_down_.load(std::memory_order_acquire) && + bg_error_.ok()) { + if (manual_compaction_ == nullptr) { // Idle + manual_compaction_ = &manual; + MaybeScheduleCompaction(); + } else { // Running either my compaction or another compaction. + background_work_finished_signal_.Wait(); + } + } + if (manual_compaction_ == &manual) { + // Cancel my manual compaction since we aborted early for some reason. + manual_compaction_ = nullptr; + } +} + +Status DBImpl::TEST_CompactMemTable() { + // nullptr batch means just wait for earlier writes to be done + Status s = Write(WriteOptions(), nullptr); + if (s.ok()) { + // Wait until the compaction completes + MutexLock l(&mutex_); + while (imm_ != nullptr && bg_error_.ok()) { + background_work_finished_signal_.Wait(); + } + if (imm_ != nullptr) { + s = bg_error_; + } + } + return s; +} + +void DBImpl::RecordBackgroundError(const Status& s) { + mutex_.AssertHeld(); + if (bg_error_.ok()) { + bg_error_ = s; + background_work_finished_signal_.SignalAll(); + } +} + +void DBImpl::MaybeScheduleCompaction() { + mutex_.AssertHeld(); + if (background_compaction_scheduled_) { + // Already scheduled + } else if (shutting_down_.load(std::memory_order_acquire)) { + // DB is being deleted; no more background compactions + } else if (!bg_error_.ok()) { + // Already got an error; no more changes + } else if (imm_ == nullptr && manual_compaction_ == nullptr && + !versions_->NeedsCompaction()) { + // No work to be done + } else { + background_compaction_scheduled_ = true; + env_->Schedule(&DBImpl::BGWork, this); + } +} + +void DBImpl::BGWork(void* db) { + reinterpret_cast(db)->BackgroundCall(); +} + +void DBImpl::BackgroundCall() { + MutexLock l(&mutex_); + assert(background_compaction_scheduled_); + if (shutting_down_.load(std::memory_order_acquire)) { + // No more background work when shutting down. + } else if (!bg_error_.ok()) { + // No more background work after a background error. + } else { + BackgroundCompaction(); + } + + background_compaction_scheduled_ = false; + + // Previous compaction may have produced too many files in a level, + // so reschedule another compaction if needed. + MaybeScheduleCompaction(); + background_work_finished_signal_.SignalAll(); +} + +void DBImpl::BackgroundCompaction() { + mutex_.AssertHeld(); + + if (imm_ != nullptr) { + CompactMemTable(); + return; + } + + Compaction* c; + bool is_manual = (manual_compaction_ != nullptr); + InternalKey manual_end; + if (is_manual) { + ManualCompaction* m = manual_compaction_; + c = versions_->CompactRange(m->level, m->begin, m->end); + m->done = (c == nullptr); + if (c != nullptr) { + manual_end = c->input(0, c->num_input_files(0) - 1)->largest; + } + Log(options_.info_log, + "Manual compaction at level-%d from %s .. %s; will stop at %s\n", + m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"), + (m->end ? m->end->DebugString().c_str() : "(end)"), + (m->done ? "(end)" : manual_end.DebugString().c_str())); + } else { + c = versions_->PickCompaction(); + } + + Status status; + if (c == nullptr) { + // Nothing to do + } else if (!is_manual && c->IsTrivialMove()) { + // Move file to next level + assert(c->num_input_files(0) == 1); + FileMetaData* f = c->input(0, 0); + c->edit()->DeleteFile(c->level(), f->number); + c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest, + f->largest); + status = versions_->LogAndApply(c->edit(), &mutex_); + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", + static_cast(f->number), c->level() + 1, + static_cast(f->file_size), + status.ToString().c_str(), versions_->LevelSummary(&tmp)); + } else { + CompactionState* compact = new CompactionState(c); + status = DoCompactionWork(compact); + if (!status.ok()) { + RecordBackgroundError(status); + } + CleanupCompaction(compact); + c->ReleaseInputs(); + DeleteObsoleteFiles(); + } + delete c; + + if (status.ok()) { + // Done + } else if (shutting_down_.load(std::memory_order_acquire)) { + // Ignore compaction errors found during shutting down + } else { + Log(options_.info_log, "Compaction error: %s", status.ToString().c_str()); + } + + if (is_manual) { + ManualCompaction* m = manual_compaction_; + if (!status.ok()) { + m->done = true; + } + if (!m->done) { + // We only compacted part of the requested range. Update *m + // to the range that is left to be compacted. + m->tmp_storage = manual_end; + m->begin = &m->tmp_storage; + } + manual_compaction_ = nullptr; + } +} + +void DBImpl::CleanupCompaction(CompactionState* compact) { + mutex_.AssertHeld(); + if (compact->builder != nullptr) { + // May happen if we get a shutdown call in the middle of compaction + compact->builder->Abandon(); + delete compact->builder; + } else { + assert(compact->outfile == nullptr); + } + delete compact->outfile; + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + pending_outputs_.erase(out.number); + } + delete compact; +} + +Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { + assert(compact != nullptr); + assert(compact->builder == nullptr); + uint64_t file_number; + { + mutex_.Lock(); + file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + CompactionState::Output out; + out.number = file_number; + out.smallest.Clear(); + out.largest.Clear(); + compact->outputs.push_back(out); + mutex_.Unlock(); + } + + // Make the output file + std::string fname = TableFileName(dbname_, file_number); + Status s = env_->NewWritableFile(fname, &compact->outfile); + if (s.ok()) { + compact->builder = new TableBuilder(options_, compact->outfile); + } + return s; +} + +Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, + Iterator* input) { + assert(compact != nullptr); + assert(compact->outfile != nullptr); + assert(compact->builder != nullptr); + + const uint64_t output_number = compact->current_output()->number; + assert(output_number != 0); + + // Check for iterator errors + Status s = input->status(); + const uint64_t current_entries = compact->builder->NumEntries(); + if (s.ok()) { + s = compact->builder->Finish(); + } else { + compact->builder->Abandon(); + } + const uint64_t current_bytes = compact->builder->FileSize(); + compact->current_output()->file_size = current_bytes; + compact->total_bytes += current_bytes; + delete compact->builder; + compact->builder = nullptr; + + // Finish and check for file errors + if (s.ok()) { + s = compact->outfile->Sync(); + } + if (s.ok()) { + s = compact->outfile->Close(); + } + delete compact->outfile; + compact->outfile = nullptr; + + if (s.ok() && current_entries > 0) { + // Verify that the table is usable + Iterator* iter = + table_cache_->NewIterator(ReadOptions(), output_number, current_bytes); + s = iter->status(); + delete iter; + if (s.ok()) { + Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes", + (unsigned long long)output_number, compact->compaction->level(), + (unsigned long long)current_entries, + (unsigned long long)current_bytes); + } + } + return s; +} + +Status DBImpl::InstallCompactionResults(CompactionState* compact) { + mutex_.AssertHeld(); + Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), compact->compaction->level() + 1, + static_cast(compact->total_bytes)); + + // Add compaction outputs + compact->compaction->AddInputDeletions(compact->compaction->edit()); + const int level = compact->compaction->level(); + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size, + out.smallest, out.largest); + } + return versions_->LogAndApply(compact->compaction->edit(), &mutex_); +} + +Status DBImpl::DoCompactionWork(CompactionState* compact) { + const uint64_t start_micros = env_->NowMicros(); + int64_t imm_micros = 0; // Micros spent doing imm_ compactions + + Log(options_.info_log, "Compacting %d@%d + %d@%d files", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1); + + assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); + assert(compact->builder == nullptr); + assert(compact->outfile == nullptr); + if (snapshots_.empty()) { + compact->smallest_snapshot = versions_->LastSequence(); + } else { + compact->smallest_snapshot = snapshots_.oldest()->sequence_number(); + } + + // Release mutex while we're actually doing the compaction work + mutex_.Unlock(); + + Iterator* input = versions_->MakeInputIterator(compact->compaction); + input->SeekToFirst(); + Status status; + ParsedInternalKey ikey; + std::string current_user_key; + bool has_current_user_key = false; + SequenceNumber last_sequence_for_key = kMaxSequenceNumber; + for (; input->Valid() && !shutting_down_.load(std::memory_order_acquire);) { + // Prioritize immutable compaction work + if (has_imm_.load(std::memory_order_relaxed)) { + const uint64_t imm_start = env_->NowMicros(); + mutex_.Lock(); + if (imm_ != nullptr) { + CompactMemTable(); + // Wake up MakeRoomForWrite() if necessary. + background_work_finished_signal_.SignalAll(); + } + mutex_.Unlock(); + imm_micros += (env_->NowMicros() - imm_start); + } + + Slice key = input->key(); + if (compact->compaction->ShouldStopBefore(key) && + compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + + // Handle key/value, add to state, etc. + bool drop = false; + if (!ParseInternalKey(key, &ikey)) { + // Do not hide error keys + current_user_key.clear(); + has_current_user_key = false; + last_sequence_for_key = kMaxSequenceNumber; + } else { + if (!has_current_user_key || + user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) != + 0) { + // First occurrence of this user key + current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + has_current_user_key = true; + last_sequence_for_key = kMaxSequenceNumber; + } + + if (last_sequence_for_key <= compact->smallest_snapshot) { + // Hidden by an newer entry for same user key + drop = true; // (A) + } else if (ikey.type == kTypeDeletion && + ikey.sequence <= compact->smallest_snapshot && + compact->compaction->IsBaseLevelForKey(ikey.user_key)) { + // For this user key: + // (1) there is no data in higher levels + // (2) data in lower levels will have larger sequence numbers + // (3) data in layers that are being compacted here and have + // smaller sequence numbers will be dropped in the next + // few iterations of this loop (by rule (A) above). + // Therefore this deletion marker is obsolete and can be dropped. + drop = true; + } + + last_sequence_for_key = ikey.sequence; + } +#if 0 + Log(options_.info_log, + " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " + "%d smallest_snapshot: %d", + ikey.user_key.ToString().c_str(), + (int)ikey.sequence, ikey.type, kTypeValue, drop, + compact->compaction->IsBaseLevelForKey(ikey.user_key), + (int)last_sequence_for_key, (int)compact->smallest_snapshot); +#endif + + if (!drop) { + // Open output file if necessary + if (compact->builder == nullptr) { + status = OpenCompactionOutputFile(compact); + if (!status.ok()) { + break; + } + } + if (compact->builder->NumEntries() == 0) { + compact->current_output()->smallest.DecodeFrom(key); + } + compact->current_output()->largest.DecodeFrom(key); + compact->builder->Add(key, input->value()); + + // Close output file if it is big enough + if (compact->builder->FileSize() >= + compact->compaction->MaxOutputFileSize()) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + } + + input->Next(); + } + + if (status.ok() && shutting_down_.load(std::memory_order_acquire)) { + status = Status::IOError("Deleting DB during compaction"); + } + if (status.ok() && compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + } + if (status.ok()) { + status = input->status(); + } + delete input; + input = nullptr; + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros - imm_micros; + for (int which = 0; which < 2; which++) { + for (int i = 0; i < compact->compaction->num_input_files(which); i++) { + stats.bytes_read += compact->compaction->input(which, i)->file_size; + } + } + for (size_t i = 0; i < compact->outputs.size(); i++) { + stats.bytes_written += compact->outputs[i].file_size; + } + + mutex_.Lock(); + stats_[compact->compaction->level() + 1].Add(stats); + + if (status.ok()) { + status = InstallCompactionResults(compact); + } + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp)); + return status; +} + +namespace { + +struct IterState { + port::Mutex* const mu; + Version* const version GUARDED_BY(mu); + MemTable* const mem GUARDED_BY(mu); + MemTable* const imm GUARDED_BY(mu); + + IterState(port::Mutex* mutex, MemTable* mem, MemTable* imm, Version* version) + : mu(mutex), version(version), mem(mem), imm(imm) {} +}; + +static void CleanupIteratorState(void* arg1, void* arg2) { + IterState* state = reinterpret_cast(arg1); + state->mu->Lock(); + state->mem->Unref(); + if (state->imm != nullptr) state->imm->Unref(); + state->version->Unref(); + state->mu->Unlock(); + delete state; +} + +} // anonymous namespace + +Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, + SequenceNumber* latest_snapshot, + uint32_t* seed) { + mutex_.Lock(); + *latest_snapshot = versions_->LastSequence(); + + // Collect together all needed child iterators + std::vector list; + list.push_back(mem_->NewIterator()); + mem_->Ref(); + if (imm_ != nullptr) { + list.push_back(imm_->NewIterator()); + imm_->Ref(); + } + versions_->current()->AddIterators(options, &list); + Iterator* internal_iter = + NewMergingIterator(&internal_comparator_, &list[0], list.size()); + versions_->current()->Ref(); + + IterState* cleanup = new IterState(&mutex_, mem_, imm_, versions_->current()); + internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr); + + *seed = ++seed_; + mutex_.Unlock(); + return internal_iter; +} + +Iterator* DBImpl::TEST_NewInternalIterator() { + SequenceNumber ignored; + uint32_t ignored_seed; + return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed); +} + +int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { + MutexLock l(&mutex_); + return versions_->MaxNextLevelOverlappingBytes(); +} + +Status DBImpl::Get(const ReadOptions& options, const Slice& key, + std::string* value) { + Status s; + MutexLock l(&mutex_); + SequenceNumber snapshot; + if (options.snapshot != nullptr) { + snapshot = + static_cast(options.snapshot)->sequence_number(); + } else { + snapshot = versions_->LastSequence(); + } + + MemTable* mem = mem_; + MemTable* imm = imm_; + Version* current = versions_->current(); + mem->Ref(); + if (imm != nullptr) imm->Ref(); + current->Ref(); + + bool have_stat_update = false; + Version::GetStats stats; + + // Unlock while reading from files and memtables + { + mutex_.Unlock(); + // First look in the memtable, then in the immutable memtable (if any). + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + // Done + } else if (imm != nullptr && imm->Get(lkey, value, &s)) { + // Done + } else { + s = current->Get(options, lkey, value, &stats); + have_stat_update = true; + } + mutex_.Lock(); + } + + if (have_stat_update && current->UpdateStats(stats)) { + MaybeScheduleCompaction(); + } + mem->Unref(); + if (imm != nullptr) imm->Unref(); + current->Unref(); + return s; +} + +Iterator* DBImpl::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + uint32_t seed; + Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed); + return NewDBIterator(this, user_comparator(), iter, + (options.snapshot != nullptr + ? static_cast(options.snapshot) + ->sequence_number() + : latest_snapshot), + seed); +} + +void DBImpl::RecordReadSample(Slice key) { + MutexLock l(&mutex_); + if (versions_->current()->RecordReadSample(key)) { + MaybeScheduleCompaction(); + } +} + +const Snapshot* DBImpl::GetSnapshot() { + MutexLock l(&mutex_); + return snapshots_.New(versions_->LastSequence()); +} + +void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) { + MutexLock l(&mutex_); + snapshots_.Delete(static_cast(snapshot)); +} + +// Convenience methods +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + return DB::Put(o, key, val); +} + +Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { + return DB::Delete(options, key); +} + +Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) { + Writer w(&mutex_); + w.batch = updates; + w.sync = options.sync; + w.done = false; + + MutexLock l(&mutex_); + writers_.push_back(&w); + while (!w.done && &w != writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + // May temporarily unlock and wait. + Status status = MakeRoomForWrite(updates == nullptr); + uint64_t last_sequence = versions_->LastSequence(); + Writer* last_writer = &w; + if (status.ok() && updates != nullptr) { // nullptr batch is for compactions + WriteBatch* updates = BuildBatchGroup(&last_writer); + WriteBatchInternal::SetSequence(updates, last_sequence + 1); + last_sequence += WriteBatchInternal::Count(updates); + + // Add to log and apply to memtable. We can release the lock + // during this phase since &w is currently responsible for logging + // and protects against concurrent loggers and concurrent writes + // into mem_. + { + mutex_.Unlock(); + status = log_->AddRecord(WriteBatchInternal::Contents(updates)); + bool sync_error = false; + if (status.ok() && options.sync) { + status = logfile_->Sync(); + if (!status.ok()) { + sync_error = true; + } + } + if (status.ok()) { + status = WriteBatchInternal::InsertInto(updates, mem_); + } + mutex_.Lock(); + if (sync_error) { + // The state of the log file is indeterminate: the log record we + // just added may or may not show up when the DB is re-opened. + // So we force the DB into a mode where all future writes fail. + RecordBackgroundError(status); + } + } + if (updates == tmp_batch_) tmp_batch_->Clear(); + + versions_->SetLastSequence(last_sequence); + } + + while (true) { + Writer* ready = writers_.front(); + writers_.pop_front(); + if (ready != &w) { + ready->status = status; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + + // Notify new head of write queue + if (!writers_.empty()) { + writers_.front()->cv.Signal(); + } + + return status; +} + +// REQUIRES: Writer list must be non-empty +// REQUIRES: First writer must have a non-null batch +WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + Writer* first = writers_.front(); + WriteBatch* result = first->batch; + assert(result != nullptr); + + size_t size = WriteBatchInternal::ByteSize(first->batch); + + // Allow the group to grow up to a maximum size, but if the + // original write is small, limit the growth so we do not slow + // down the small write too much. + size_t max_size = 1 << 20; + if (size <= (128 << 10)) { + max_size = size + (128 << 10); + } + + *last_writer = first; + std::deque::iterator iter = writers_.begin(); + ++iter; // Advance past "first" + for (; iter != writers_.end(); ++iter) { + Writer* w = *iter; + if (w->sync && !first->sync) { + // Do not include a sync write into a batch handled by a non-sync write. + break; + } + + if (w->batch != nullptr) { + size += WriteBatchInternal::ByteSize(w->batch); + if (size > max_size) { + // Do not make batch too big + break; + } + + // Append to *result + if (result == first->batch) { + // Switch to temporary batch instead of disturbing caller's batch + result = tmp_batch_; + assert(WriteBatchInternal::Count(result) == 0); + WriteBatchInternal::Append(result, first->batch); + } + WriteBatchInternal::Append(result, w->batch); + } + *last_writer = w; + } + return result; +} + +// REQUIRES: mutex_ is held +// REQUIRES: this thread is currently at the front of the writer queue +Status DBImpl::MakeRoomForWrite(bool force) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + bool allow_delay = !force; + Status s; + while (true) { + if (!bg_error_.ok()) { + // Yield previous error + s = bg_error_; + break; + } else if (allow_delay && versions_->NumLevelFiles(0) >= + config::kL0_SlowdownWritesTrigger) { + // We are getting close to hitting a hard limit on the number of + // L0 files. Rather than delaying a single write by several + // seconds when we hit the hard limit, start delaying each + // individual write by 1ms to reduce latency variance. Also, + // this delay hands over some CPU to the compaction thread in + // case it is sharing the same core as the writer. + mutex_.Unlock(); + env_->SleepForMicroseconds(1000); + allow_delay = false; // Do not delay a single write more than once + mutex_.Lock(); + } else if (!force && + (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { + // There is room in current memtable + break; + } else if (imm_ != nullptr) { + // We have filled up the current memtable, but the previous + // one is still being compacted, so we wait. + Log(options_.info_log, "Current memtable full; waiting...\n"); + background_work_finished_signal_.Wait(); + } else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) { + // There are too many level-0 files. + Log(options_.info_log, "Too many L0 files; waiting...\n"); + background_work_finished_signal_.Wait(); + } else { + // Attempt to switch to a new memtable and trigger compaction of old + assert(versions_->PrevLogNumber() == 0); + uint64_t new_log_number = versions_->NewFileNumber(); + WritableFile* lfile = nullptr; + s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); + if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); + break; + } + delete log_; + delete logfile_; + logfile_ = lfile; + logfile_number_ = new_log_number; + log_ = new log::Writer(lfile); + imm_ = mem_; + has_imm_.store(true, std::memory_order_release); + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + force = false; // Do not force another compaction if have room + MaybeScheduleCompaction(); + } + } + return s; +} + +bool DBImpl::GetProperty(const Slice& property, std::string* value) { + value->clear(); + + MutexLock l(&mutex_); + Slice in = property; + Slice prefix("leveldb."); + if (!in.starts_with(prefix)) return false; + in.remove_prefix(prefix.size()); + + if (in.starts_with("num-files-at-level")) { + in.remove_prefix(strlen("num-files-at-level")); + uint64_t level; + bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); + if (!ok || level >= config::kNumLevels) { + return false; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "%d", + versions_->NumLevelFiles(static_cast(level))); + *value = buf; + return true; + } + } else if (in == "stats") { + char buf[200]; + snprintf(buf, sizeof(buf), + " Compactions\n" + "Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n" + "--------------------------------------------------\n"); + value->append(buf); + for (int level = 0; level < config::kNumLevels; level++) { + int files = versions_->NumLevelFiles(level); + if (stats_[level].micros > 0 || files > 0) { + snprintf(buf, sizeof(buf), "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", level, + files, versions_->NumLevelBytes(level) / 1048576.0, + stats_[level].micros / 1e6, + stats_[level].bytes_read / 1048576.0, + stats_[level].bytes_written / 1048576.0); + value->append(buf); + } + } + return true; + } else if (in == "sstables") { + *value = versions_->current()->DebugString(); + return true; + } else if (in == "approximate-memory-usage") { + size_t total_usage = options_.block_cache->TotalCharge(); + if (mem_) { + total_usage += mem_->ApproximateMemoryUsage(); + } + if (imm_) { + total_usage += imm_->ApproximateMemoryUsage(); + } + char buf[50]; + snprintf(buf, sizeof(buf), "%llu", + static_cast(total_usage)); + value->append(buf); + return true; + } + + return false; +} + +void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { + // TODO(opt): better implementation + Version* v; + { + MutexLock l(&mutex_); + versions_->current()->Ref(); + v = versions_->current(); + } + + for (int i = 0; i < n; i++) { + // Convert user_key into a corresponding internal key. + InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); + uint64_t start = versions_->ApproximateOffsetOf(v, k1); + uint64_t limit = versions_->ApproximateOffsetOf(v, k2); + sizes[i] = (limit >= start ? limit - start : 0); + } + + { + MutexLock l(&mutex_); + v->Unref(); + } +} + +// Default implementations of convenience methods that subclasses of DB +// can call if they wish +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { + WriteBatch batch; + batch.Put(key, value); + return Write(opt, &batch); +} + +Status DB::Delete(const WriteOptions& opt, const Slice& key) { + WriteBatch batch; + batch.Delete(key); + return Write(opt, &batch); +} + +DB::~DB() {} + +Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) { + *dbptr = nullptr; + + DBImpl* impl = new DBImpl(options, dbname); + impl->mutex_.Lock(); + VersionEdit edit; + // Recover handles create_if_missing, error_if_exists + bool save_manifest = false; + Status s = impl->Recover(&edit, &save_manifest); + if (s.ok() && impl->mem_ == nullptr) { + // Create new log and a corresponding memtable. + uint64_t new_log_number = impl->versions_->NewFileNumber(); + WritableFile* lfile; + s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), + &lfile); + if (s.ok()) { + edit.SetLogNumber(new_log_number); + impl->logfile_ = lfile; + impl->logfile_number_ = new_log_number; + impl->log_ = new log::Writer(lfile); + impl->mem_ = new MemTable(impl->internal_comparator_); + impl->mem_->Ref(); + } + } + if (s.ok() && save_manifest) { + edit.SetPrevLogNumber(0); // No older logs needed after recovery. + edit.SetLogNumber(impl->logfile_number_); + s = impl->versions_->LogAndApply(&edit, &impl->mutex_); + } + if (s.ok()) { + impl->DeleteObsoleteFiles(); + impl->MaybeScheduleCompaction(); + } + impl->mutex_.Unlock(); + if (s.ok()) { + assert(impl->mem_ != nullptr); + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +Snapshot::~Snapshot() {} + +Status DestroyDB(const std::string& dbname, const Options& options) { + Env* env = options.env; + std::vector filenames; + Status result = env->GetChildren(dbname, &filenames); + if (!result.ok()) { + // Ignore error in case directory does not exist + return Status::OK(); + } + + FileLock* lock; + const std::string lockname = LockFileName(dbname); + result = env->LockFile(lockname, &lock); + if (result.ok()) { + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type != kDBLockFile) { // Lock file will be deleted at end + Status del = env->DeleteFile(dbname + "/" + filenames[i]); + if (result.ok() && !del.ok()) { + result = del; + } + } + } + env->UnlockFile(lock); // Ignore error since state is already gone + env->DeleteFile(lockname); + env->DeleteDir(dbname); // Ignore error in case dir contains other files + } + return result; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/db_impl.h b/MyExperiences copy/Pods/leveldb-library/db/db_impl.h new file mode 100644 index 00000000..ae87d6e3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/db_impl.h @@ -0,0 +1,216 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_H_ + +#include +#include +#include +#include + +#include "db/dbformat.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +class MemTable; +class TableCache; +class Version; +class VersionEdit; +class VersionSet; + +class DBImpl : public DB { + public: + DBImpl(const Options& options, const std::string& dbname); + + DBImpl(const DBImpl&) = delete; + DBImpl& operator=(const DBImpl&) = delete; + + virtual ~DBImpl(); + + // Implementations of the DB interface + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); + virtual Status Delete(const WriteOptions&, const Slice& key); + virtual Status Write(const WriteOptions& options, WriteBatch* updates); + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + virtual const Snapshot* GetSnapshot(); + virtual void ReleaseSnapshot(const Snapshot* snapshot); + virtual bool GetProperty(const Slice& property, std::string* value); + virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); + virtual void CompactRange(const Slice* begin, const Slice* end); + + // Extra methods (for testing) that are not in the public DB interface + + // Compact any files in the named level that overlap [*begin,*end] + void TEST_CompactRange(int level, const Slice* begin, const Slice* end); + + // Force current memtable contents to be compacted. + Status TEST_CompactMemTable(); + + // Return an internal iterator over the current state of the database. + // The keys of this iterator are internal keys (see format.h). + // The returned iterator should be deleted when no longer needed. + Iterator* TEST_NewInternalIterator(); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t TEST_MaxNextLevelOverlappingBytes(); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. + void RecordReadSample(Slice key); + + private: + friend class DB; + struct CompactionState; + struct Writer; + + // Information for a manual compaction + struct ManualCompaction { + int level; + bool done; + const InternalKey* begin; // null means beginning of key range + const InternalKey* end; // null means end of key range + InternalKey tmp_storage; // Used to keep track of compaction progress + }; + + // Per level compaction stats. stats_[level] stores the stats for + // compactions that produced data for the specified "level". + struct CompactionStats { + CompactionStats() : micros(0), bytes_read(0), bytes_written(0) {} + + void Add(const CompactionStats& c) { + this->micros += c.micros; + this->bytes_read += c.bytes_read; + this->bytes_written += c.bytes_written; + } + + int64_t micros; + int64_t bytes_read; + int64_t bytes_written; + }; + + Iterator* NewInternalIterator(const ReadOptions&, + SequenceNumber* latest_snapshot, + uint32_t* seed); + + Status NewDB(); + + // Recover the descriptor from persistent storage. May do a significant + // amount of work to recover recently logged updates. Any changes to + // be made to the descriptor are added to *edit. + Status Recover(VersionEdit* edit, bool* save_manifest) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void MaybeIgnoreError(Status* s) const; + + // Delete any unneeded files and stale in-memory entries. + void DeleteObsoleteFiles() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Compact the in-memory write buffer to disk. Switches to a new + // log-file/memtable and writes a new descriptor iff successful. + // Errors are recorded in bg_error_. + void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status RecoverLogFile(uint64_t log_number, bool last_log, bool* save_manifest, + VersionEdit* edit, SequenceNumber* max_sequence) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status MakeRoomForWrite(bool force /* compact even if there is room? */) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + WriteBatch* BuildBatchGroup(Writer** last_writer) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void RecordBackgroundError(const Status& s); + + void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + static void BGWork(void* db); + void BackgroundCall(); + void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void CleanupCompaction(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + Status DoCompactionWork(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status OpenCompactionOutputFile(CompactionState* compact); + Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); + Status InstallCompactionResults(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + const Comparator* user_comparator() const { + return internal_comparator_.user_comparator(); + } + + // Constant after construction + Env* const env_; + const InternalKeyComparator internal_comparator_; + const InternalFilterPolicy internal_filter_policy_; + const Options options_; // options_.comparator == &internal_comparator_ + const bool owns_info_log_; + const bool owns_cache_; + const std::string dbname_; + + // table_cache_ provides its own synchronization + TableCache* const table_cache_; + + // Lock over the persistent DB state. Non-null iff successfully acquired. + FileLock* db_lock_; + + // State below is protected by mutex_ + port::Mutex mutex_; + std::atomic shutting_down_; + port::CondVar background_work_finished_signal_ GUARDED_BY(mutex_); + MemTable* mem_; + MemTable* imm_ GUARDED_BY(mutex_); // Memtable being compacted + std::atomic has_imm_; // So bg thread can detect non-null imm_ + WritableFile* logfile_; + uint64_t logfile_number_ GUARDED_BY(mutex_); + log::Writer* log_; + uint32_t seed_ GUARDED_BY(mutex_); // For sampling. + + // Queue of writers. + std::deque writers_ GUARDED_BY(mutex_); + WriteBatch* tmp_batch_ GUARDED_BY(mutex_); + + SnapshotList snapshots_ GUARDED_BY(mutex_); + + // Set of table files to protect from deletion because they are + // part of ongoing compactions. + std::set pending_outputs_ GUARDED_BY(mutex_); + + // Has a background compaction been scheduled or is running? + bool background_compaction_scheduled_ GUARDED_BY(mutex_); + + ManualCompaction* manual_compaction_ GUARDED_BY(mutex_); + + VersionSet* const versions_; + + // Have we encountered a background error in paranoid mode? + Status bg_error_ GUARDED_BY(mutex_); + + CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_); +}; + +// Sanitize db options. The caller should delete result.info_log if +// it is not equal to src.info_log. +Options SanitizeOptions(const std::string& db, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/db_iter.cc b/MyExperiences copy/Pods/leveldb-library/db/db_iter.cc new file mode 100644 index 00000000..8ff288e4 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/db_iter.cc @@ -0,0 +1,309 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_iter.h" + +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/random.h" + +namespace leveldb { + +#if 0 +static void DumpInternalIter(Iterator* iter) { + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey k; + if (!ParseInternalKey(iter->key(), &k)) { + fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); + } else { + fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); + } + } +} +#endif + +namespace { + +// Memtables and sstables that make the DB representation contain +// (userkey,seq,type) => uservalue entries. DBIter +// combines multiple entries for the same userkey found in the DB +// representation into a single entry while accounting for sequence +// numbers, deletion markers, overwrites, etc. +class DBIter : public Iterator { + public: + // Which direction is the iterator currently moving? + // (1) When moving forward, the internal iterator is positioned at + // the exact entry that yields this->key(), this->value() + // (2) When moving backwards, the internal iterator is positioned + // just before all entries whose user key == this->key(). + enum Direction { kForward, kReverse }; + + DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s, + uint32_t seed) + : db_(db), + user_comparator_(cmp), + iter_(iter), + sequence_(s), + direction_(kForward), + valid_(false), + rnd_(seed), + bytes_until_read_sampling_(RandomCompactionPeriod()) {} + + DBIter(const DBIter&) = delete; + DBIter& operator=(const DBIter&) = delete; + + virtual ~DBIter() { delete iter_; } + virtual bool Valid() const { return valid_; } + virtual Slice key() const { + assert(valid_); + return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; + } + virtual Slice value() const { + assert(valid_); + return (direction_ == kForward) ? iter_->value() : saved_value_; + } + virtual Status status() const { + if (status_.ok()) { + return iter_->status(); + } else { + return status_; + } + } + + virtual void Next(); + virtual void Prev(); + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + + private: + void FindNextUserEntry(bool skipping, std::string* skip); + void FindPrevUserEntry(); + bool ParseKey(ParsedInternalKey* key); + + inline void SaveKey(const Slice& k, std::string* dst) { + dst->assign(k.data(), k.size()); + } + + inline void ClearSavedValue() { + if (saved_value_.capacity() > 1048576) { + std::string empty; + swap(empty, saved_value_); + } else { + saved_value_.clear(); + } + } + + // Picks the number of bytes that can be read until a compaction is scheduled. + size_t RandomCompactionPeriod() { + return rnd_.Uniform(2 * config::kReadBytesPeriod); + } + + DBImpl* db_; + const Comparator* const user_comparator_; + Iterator* const iter_; + SequenceNumber const sequence_; + Status status_; + std::string saved_key_; // == current key when direction_==kReverse + std::string saved_value_; // == current raw value when direction_==kReverse + Direction direction_; + bool valid_; + Random rnd_; + size_t bytes_until_read_sampling_; +}; + +inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { + Slice k = iter_->key(); + + size_t bytes_read = k.size() + iter_->value().size(); + while (bytes_until_read_sampling_ < bytes_read) { + bytes_until_read_sampling_ += RandomCompactionPeriod(); + db_->RecordReadSample(k); + } + assert(bytes_until_read_sampling_ >= bytes_read); + bytes_until_read_sampling_ -= bytes_read; + + if (!ParseInternalKey(k, ikey)) { + status_ = Status::Corruption("corrupted internal key in DBIter"); + return false; + } else { + return true; + } +} + +void DBIter::Next() { + assert(valid_); + + if (direction_ == kReverse) { // Switch directions? + direction_ = kForward; + // iter_ is pointing just before the entries for this->key(), + // so advance into the range of entries for this->key() and then + // use the normal skipping code below. + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } else { + iter_->Next(); + } + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + return; + } + // saved_key_ already contains the key to skip past. + } else { + // Store in saved_key_ the current key so we skip it below. + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + } + + FindNextUserEntry(true, &saved_key_); +} + +void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { + // Loop until we hit an acceptable entry to yield + assert(iter_->Valid()); + assert(direction_ == kForward); + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + switch (ikey.type) { + case kTypeDeletion: + // Arrange to skip all upcoming entries for this key since + // they are hidden by this deletion. + SaveKey(ikey.user_key, skip); + skipping = true; + break; + case kTypeValue: + if (skipping && + user_comparator_->Compare(ikey.user_key, *skip) <= 0) { + // Entry hidden + } else { + valid_ = true; + saved_key_.clear(); + return; + } + break; + } + } + iter_->Next(); + } while (iter_->Valid()); + saved_key_.clear(); + valid_ = false; +} + +void DBIter::Prev() { + assert(valid_); + + if (direction_ == kForward) { // Switch directions? + // iter_ is pointing at the current entry. Scan backwards until + // the key changes so we can use the normal reverse scanning code. + assert(iter_->Valid()); // Otherwise valid_ would have been false + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + while (true) { + iter_->Prev(); + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + return; + } + if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) < + 0) { + break; + } + } + direction_ = kReverse; + } + + FindPrevUserEntry(); +} + +void DBIter::FindPrevUserEntry() { + assert(direction_ == kReverse); + + ValueType value_type = kTypeDeletion; + if (iter_->Valid()) { + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + if ((value_type != kTypeDeletion) && + user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { + // We encountered a non-deleted value in entries for previous keys, + break; + } + value_type = ikey.type; + if (value_type == kTypeDeletion) { + saved_key_.clear(); + ClearSavedValue(); + } else { + Slice raw_value = iter_->value(); + if (saved_value_.capacity() > raw_value.size() + 1048576) { + std::string empty; + swap(empty, saved_value_); + } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + saved_value_.assign(raw_value.data(), raw_value.size()); + } + } + iter_->Prev(); + } while (iter_->Valid()); + } + + if (value_type == kTypeDeletion) { + // End + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + direction_ = kForward; + } else { + valid_ = true; + } +} + +void DBIter::Seek(const Slice& target) { + direction_ = kForward; + ClearSavedValue(); + saved_key_.clear(); + AppendInternalKey(&saved_key_, + ParsedInternalKey(target, sequence_, kValueTypeForSeek)); + iter_->Seek(saved_key_); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToFirst() { + direction_ = kForward; + ClearSavedValue(); + iter_->SeekToFirst(); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToLast() { + direction_ = kReverse; + ClearSavedValue(); + iter_->SeekToLast(); + FindPrevUserEntry(); +} + +} // anonymous namespace + +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed) { + return new DBIter(db, user_key_comparator, internal_iter, sequence, seed); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/db_iter.h b/MyExperiences copy/Pods/leveldb-library/db/db_iter.h new file mode 100644 index 00000000..fd93e912 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/db_iter.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ +#define STORAGE_LEVELDB_DB_DB_ITER_H_ + +#include + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class DBImpl; + +// Return a new iterator that converts internal keys (yielded by +// "*internal_iter") that were live at the specified "sequence" number +// into appropriate user keys. +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/dbformat.cc b/MyExperiences copy/Pods/leveldb-library/db/dbformat.cc new file mode 100644 index 00000000..69e8dc6a --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/dbformat.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/dbformat.h" + +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { + +static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { + assert(seq <= kMaxSequenceNumber); + assert(t <= kValueTypeForSeek); + return (seq << 8) | t; +} + +void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { + result->append(key.user_key.data(), key.user_key.size()); + PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); +} + +std::string ParsedInternalKey::DebugString() const { + char buf[50]; + snprintf(buf, sizeof(buf), "' @ %llu : %d", (unsigned long long)sequence, + int(type)); + std::string result = "'"; + result += EscapeString(user_key.ToString()); + result += buf; + return result; +} + +std::string InternalKey::DebugString() const { + std::string result; + ParsedInternalKey parsed; + if (ParseInternalKey(rep_, &parsed)) { + result = parsed.DebugString(); + } else { + result = "(bad)"; + result.append(EscapeString(rep_)); + } + return result; +} + +const char* InternalKeyComparator::Name() const { + return "leveldb.InternalKeyComparator"; +} + +int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { + // Order by: + // increasing user key (according to user-supplied comparator) + // decreasing sequence number + // decreasing type (though sequence# should be enough to disambiguate) + int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); + if (r == 0) { + const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); + const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); + if (anum > bnum) { + r = -1; + } else if (anum < bnum) { + r = +1; + } + } + return r; +} + +void InternalKeyComparator::FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Attempt to shorten the user portion of the key + Slice user_start = ExtractUserKey(*start); + Slice user_limit = ExtractUserKey(limit); + std::string tmp(user_start.data(), user_start.size()); + user_comparator_->FindShortestSeparator(&tmp, user_limit); + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*start, tmp) < 0); + assert(this->Compare(tmp, limit) < 0); + start->swap(tmp); + } +} + +void InternalKeyComparator::FindShortSuccessor(std::string* key) const { + Slice user_key = ExtractUserKey(*key); + std::string tmp(user_key.data(), user_key.size()); + user_comparator_->FindShortSuccessor(&tmp); + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*key, tmp) < 0); + key->swap(tmp); + } +} + +const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); } + +void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, + std::string* dst) const { + // We rely on the fact that the code in table.cc does not mind us + // adjusting keys[]. + Slice* mkey = const_cast(keys); + for (int i = 0; i < n; i++) { + mkey[i] = ExtractUserKey(keys[i]); + // TODO(sanjay): Suppress dups? + } + user_policy_->CreateFilter(keys, n, dst); +} + +bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { + return user_policy_->KeyMayMatch(ExtractUserKey(key), f); +} + +LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { + size_t usize = user_key.size(); + size_t needed = usize + 13; // A conservative estimate + char* dst; + if (needed <= sizeof(space_)) { + dst = space_; + } else { + dst = new char[needed]; + } + start_ = dst; + dst = EncodeVarint32(dst, usize + 8); + kstart_ = dst; + memcpy(dst, user_key.data(), usize); + dst += usize; + EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); + dst += 8; + end_ = dst; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/dbformat.h b/MyExperiences copy/Pods/leveldb-library/db/dbformat.h new file mode 100644 index 00000000..013028a7 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/dbformat.h @@ -0,0 +1,218 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_ +#define STORAGE_LEVELDB_DB_DBFORMAT_H_ + +#include + +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "leveldb/slice.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +// Grouping of constants. We may want to make some of these +// parameters set via options. +namespace config { +static const int kNumLevels = 7; + +// Level-0 compaction is started when we hit this many files. +static const int kL0_CompactionTrigger = 4; + +// Soft limit on number of level-0 files. We slow down writes at this point. +static const int kL0_SlowdownWritesTrigger = 8; + +// Maximum number of level-0 files. We stop writes at this point. +static const int kL0_StopWritesTrigger = 12; + +// Maximum level to which a new compacted memtable is pushed if it +// does not create overlap. We try to push to level 2 to avoid the +// relatively expensive level 0=>1 compactions and to avoid some +// expensive manifest file operations. We do not push all the way to +// the largest level since that can generate a lot of wasted disk +// space if the same key space is being repeatedly overwritten. +static const int kMaxMemCompactLevel = 2; + +// Approximate gap in bytes between samples of data read during iteration. +static const int kReadBytesPeriod = 1048576; + +} // namespace config + +class InternalKey; + +// Value types encoded as the last component of internal keys. +// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk +// data structures. +enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 }; +// kValueTypeForSeek defines the ValueType that should be passed when +// constructing a ParsedInternalKey object for seeking to a particular +// sequence number (since we sort sequence numbers in decreasing order +// and the value type is embedded as the low 8 bits in the sequence +// number in internal keys, we need to use the highest-numbered +// ValueType, not the lowest). +static const ValueType kValueTypeForSeek = kTypeValue; + +typedef uint64_t SequenceNumber; + +// We leave eight bits empty at the bottom so a type and sequence# +// can be packed together into 64-bits. +static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1); + +struct ParsedInternalKey { + Slice user_key; + SequenceNumber sequence; + ValueType type; + + ParsedInternalKey() {} // Intentionally left uninitialized (for speed) + ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) + : user_key(u), sequence(seq), type(t) {} + std::string DebugString() const; +}; + +// Return the length of the encoding of "key". +inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { + return key.user_key.size() + 8; +} + +// Append the serialization of "key" to *result. +void AppendInternalKey(std::string* result, const ParsedInternalKey& key); + +// Attempt to parse an internal key from "internal_key". On success, +// stores the parsed data in "*result", and returns true. +// +// On error, returns false, leaves "*result" in an undefined state. +bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result); + +// Returns the user key portion of an internal key. +inline Slice ExtractUserKey(const Slice& internal_key) { + assert(internal_key.size() >= 8); + return Slice(internal_key.data(), internal_key.size() - 8); +} + +// A comparator for internal keys that uses a specified comparator for +// the user key portion and breaks ties by decreasing sequence number. +class InternalKeyComparator : public Comparator { + private: + const Comparator* user_comparator_; + + public: + explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {} + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + const Comparator* user_comparator() const { return user_comparator_; } + + int Compare(const InternalKey& a, const InternalKey& b) const; +}; + +// Filter policy wrapper that converts from internal keys to user keys +class InternalFilterPolicy : public FilterPolicy { + private: + const FilterPolicy* const user_policy_; + + public: + explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {} + virtual const char* Name() const; + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; +}; + +// Modules in this directory should keep internal keys wrapped inside +// the following class instead of plain strings so that we do not +// incorrectly use string comparisons instead of an InternalKeyComparator. +class InternalKey { + private: + std::string rep_; + + public: + InternalKey() {} // Leave rep_ as empty to indicate it is invalid + InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { + AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); + } + + void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } + Slice Encode() const { + assert(!rep_.empty()); + return rep_; + } + + Slice user_key() const { return ExtractUserKey(rep_); } + + void SetFrom(const ParsedInternalKey& p) { + rep_.clear(); + AppendInternalKey(&rep_, p); + } + + void Clear() { rep_.clear(); } + + std::string DebugString() const; +}; + +inline int InternalKeyComparator::Compare(const InternalKey& a, + const InternalKey& b) const { + return Compare(a.Encode(), b.Encode()); +} + +inline bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result) { + const size_t n = internal_key.size(); + if (n < 8) return false; + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + result->sequence = num >> 8; + result->type = static_cast(c); + result->user_key = Slice(internal_key.data(), n - 8); + return (c <= static_cast(kTypeValue)); +} + +// A helper class useful for DBImpl::Get() +class LookupKey { + public: + // Initialize *this for looking up user_key at a snapshot with + // the specified sequence number. + LookupKey(const Slice& user_key, SequenceNumber sequence); + + LookupKey(const LookupKey&) = delete; + LookupKey& operator=(const LookupKey&) = delete; + + ~LookupKey(); + + // Return a key suitable for lookup in a MemTable. + Slice memtable_key() const { return Slice(start_, end_ - start_); } + + // Return an internal key (suitable for passing to an internal iterator) + Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } + + // Return the user key + Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } + + private: + // We construct a char array of the form: + // klength varint32 <-- start_ + // userkey char[klength] <-- kstart_ + // tag uint64 + // <-- end_ + // The array is a suitable MemTable key. + // The suffix starting with "userkey" can be used as an InternalKey. + const char* start_; + const char* kstart_; + const char* end_; + char space_[200]; // Avoid allocation for short keys +}; + +inline LookupKey::~LookupKey() { + if (start_ != space_) delete[] start_; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DBFORMAT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/dumpfile.cc b/MyExperiences copy/Pods/leveldb-library/db/dumpfile.cc new file mode 100644 index 00000000..9d22d58d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/dumpfile.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/dumpfile.h" + +#include + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "util/logging.h" + +namespace leveldb { + +namespace { + +bool GuessType(const std::string& fname, FileType* type) { + size_t pos = fname.rfind('/'); + std::string basename; + if (pos == std::string::npos) { + basename = fname; + } else { + basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1); + } + uint64_t ignored; + return ParseFileName(basename, &ignored, type); +} + +// Notified when log reader encounters corruption. +class CorruptionReporter : public log::Reader::Reporter { + public: + virtual void Corruption(size_t bytes, const Status& status) { + std::string r = "corruption: "; + AppendNumberTo(&r, bytes); + r += " bytes; "; + r += status.ToString(); + r.push_back('\n'); + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Print contents of a log file. (*func)() is called on every record. +Status PrintLogContents(Env* env, const std::string& fname, + void (*func)(uint64_t, Slice, WritableFile*), + WritableFile* dst) { + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + CorruptionReporter reporter; + reporter.dst_ = dst; + log::Reader reader(file, &reporter, true, 0); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch)) { + (*func)(reader.LastRecordOffset(), record, dst); + } + delete file; + return Status::OK(); +} + +// Called on every item found in a WriteBatch. +class WriteBatchItemPrinter : public WriteBatch::Handler { + public: + virtual void Put(const Slice& key, const Slice& value) { + std::string r = " put '"; + AppendEscapedStringTo(&r, key); + r += "' '"; + AppendEscapedStringTo(&r, value); + r += "'\n"; + dst_->Append(r); + } + virtual void Delete(const Slice& key) { + std::string r = " del '"; + AppendEscapedStringTo(&r, key); + r += "'\n"; + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Called on every log record (each one of which is a WriteBatch) +// found in a kLogFile. +static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + if (record.size() < 12) { + r += "log record length "; + AppendNumberTo(&r, record.size()); + r += " is too small\n"; + dst->Append(r); + return; + } + WriteBatch batch; + WriteBatchInternal::SetContents(&batch, record); + r += "sequence "; + AppendNumberTo(&r, WriteBatchInternal::Sequence(&batch)); + r.push_back('\n'); + dst->Append(r); + WriteBatchItemPrinter batch_item_printer; + batch_item_printer.dst_ = dst; + Status s = batch.Iterate(&batch_item_printer); + if (!s.ok()) { + dst->Append(" error: " + s.ToString() + "\n"); + } +} + +Status DumpLog(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, WriteBatchPrinter, dst); +} + +// Called on every log record (each one of which is a WriteBatch) +// found in a kDescriptorFile. +static void VersionEditPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + VersionEdit edit; + Status s = edit.DecodeFrom(record); + if (!s.ok()) { + r += s.ToString(); + r.push_back('\n'); + } else { + r += edit.DebugString(); + } + dst->Append(r); +} + +Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, VersionEditPrinter, dst); +} + +Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) { + uint64_t file_size; + RandomAccessFile* file = nullptr; + Table* table = nullptr; + Status s = env->GetFileSize(fname, &file_size); + if (s.ok()) { + s = env->NewRandomAccessFile(fname, &file); + } + if (s.ok()) { + // We use the default comparator, which may or may not match the + // comparator used in this database. However this should not cause + // problems since we only use Table operations that do not require + // any comparisons. In particular, we do not call Seek or Prev. + s = Table::Open(Options(), file, file_size, &table); + } + if (!s.ok()) { + delete table; + delete file; + return s; + } + + ReadOptions ro; + ro.fill_cache = false; + Iterator* iter = table->NewIterator(ro); + std::string r; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + r.clear(); + ParsedInternalKey key; + if (!ParseInternalKey(iter->key(), &key)) { + r = "badkey '"; + AppendEscapedStringTo(&r, iter->key()); + r += "' => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } else { + r = "'"; + AppendEscapedStringTo(&r, key.user_key); + r += "' @ "; + AppendNumberTo(&r, key.sequence); + r += " : "; + if (key.type == kTypeDeletion) { + r += "del"; + } else if (key.type == kTypeValue) { + r += "val"; + } else { + AppendNumberTo(&r, key.type); + } + r += " => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } + } + s = iter->status(); + if (!s.ok()) { + dst->Append("iterator error: " + s.ToString() + "\n"); + } + + delete iter; + delete table; + delete file; + return Status::OK(); +} + +} // namespace + +Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) { + FileType ftype; + if (!GuessType(fname, &ftype)) { + return Status::InvalidArgument(fname + ": unknown file type"); + } + switch (ftype) { + case kLogFile: + return DumpLog(env, fname, dst); + case kDescriptorFile: + return DumpDescriptor(env, fname, dst); + case kTableFile: + return DumpTable(env, fname, dst); + default: + break; + } + return Status::InvalidArgument(fname + ": not a dump-able file type"); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/filename.cc b/MyExperiences copy/Pods/leveldb-library/db/filename.cc new file mode 100644 index 00000000..85de45c5 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/filename.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include +#include + +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "util/logging.h" + +namespace leveldb { + +// A utility routine: write "data" to the named file and Sync() it. +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname); + +static std::string MakeFileName(const std::string& dbname, uint64_t number, + const char* suffix) { + char buf[100]; + snprintf(buf, sizeof(buf), "/%06llu.%s", + static_cast(number), suffix); + return dbname + buf; +} + +std::string LogFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "log"); +} + +std::string TableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "ldb"); +} + +std::string SSTTableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "sst"); +} + +std::string DescriptorFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + char buf[100]; + snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", + static_cast(number)); + return dbname + buf; +} + +std::string CurrentFileName(const std::string& dbname) { + return dbname + "/CURRENT"; +} + +std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; } + +std::string TempFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "dbtmp"); +} + +std::string InfoLogFileName(const std::string& dbname) { + return dbname + "/LOG"; +} + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname) { + return dbname + "/LOG.old"; +} + +// Owned filenames have the form: +// dbname/CURRENT +// dbname/LOCK +// dbname/LOG +// dbname/LOG.old +// dbname/MANIFEST-[0-9]+ +// dbname/[0-9]+.(log|sst|ldb) +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type) { + Slice rest(filename); + if (rest == "CURRENT") { + *number = 0; + *type = kCurrentFile; + } else if (rest == "LOCK") { + *number = 0; + *type = kDBLockFile; + } else if (rest == "LOG" || rest == "LOG.old") { + *number = 0; + *type = kInfoLogFile; + } else if (rest.starts_with("MANIFEST-")) { + rest.remove_prefix(strlen("MANIFEST-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kDescriptorFile; + *number = num; + } else { + // Avoid strtoull() to keep filename format independent of the + // current locale + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + Slice suffix = rest; + if (suffix == Slice(".log")) { + *type = kLogFile; + } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) { + *type = kTableFile; + } else if (suffix == Slice(".dbtmp")) { + *type = kTempFile; + } else { + return false; + } + *number = num; + } + return true; +} + +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number) { + // Remove leading "dbname/" and add newline to manifest file name + std::string manifest = DescriptorFileName(dbname, descriptor_number); + Slice contents = manifest; + assert(contents.starts_with(dbname + "/")); + contents.remove_prefix(dbname.size() + 1); + std::string tmp = TempFileName(dbname, descriptor_number); + Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); + if (s.ok()) { + s = env->RenameFile(tmp, CurrentFileName(dbname)); + } + if (!s.ok()) { + env->DeleteFile(tmp); + } + return s; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/filename.h b/MyExperiences copy/Pods/leveldb-library/db/filename.h new file mode 100644 index 00000000..524e813c --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/filename.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// File names used by DB code + +#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ +#define STORAGE_LEVELDB_DB_FILENAME_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +enum FileType { + kLogFile, + kDBLockFile, + kTableFile, + kDescriptorFile, + kCurrentFile, + kTempFile, + kInfoLogFile // Either the current one, or an old one +}; + +// Return the name of the log file with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string LogFileName(const std::string& dbname, uint64_t number); + +// Return the name of the sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string TableFileName(const std::string& dbname, uint64_t number); + +// Return the legacy file name for an sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string SSTTableFileName(const std::string& dbname, uint64_t number); + +// Return the name of the descriptor file for the db named by +// "dbname" and the specified incarnation number. The result will be +// prefixed with "dbname". +std::string DescriptorFileName(const std::string& dbname, uint64_t number); + +// Return the name of the current file. This file contains the name +// of the current manifest file. The result will be prefixed with +// "dbname". +std::string CurrentFileName(const std::string& dbname); + +// Return the name of the lock file for the db named by +// "dbname". The result will be prefixed with "dbname". +std::string LockFileName(const std::string& dbname); + +// Return the name of a temporary file owned by the db named "dbname". +// The result will be prefixed with "dbname". +std::string TempFileName(const std::string& dbname, uint64_t number); + +// Return the name of the info log file for "dbname". +std::string InfoLogFileName(const std::string& dbname); + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname); + +// If filename is a leveldb file, store the type of the file in *type. +// The number encoded in the filename is stored in *number. If the +// filename was successfully parsed, returns true. Else return false. +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type); + +// Make the CURRENT file point to the descriptor file with the +// specified number. +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/log_format.h b/MyExperiences copy/Pods/leveldb-library/db/log_format.h new file mode 100644 index 00000000..356e69fc --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/log_format.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Log format information shared by reader and writer. +// See ../doc/log_format.md for more detail. + +#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ +#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ + +namespace leveldb { +namespace log { + +enum RecordType { + // Zero is reserved for preallocated files + kZeroType = 0, + + kFullType = 1, + + // For fragments + kFirstType = 2, + kMiddleType = 3, + kLastType = 4 +}; +static const int kMaxRecordType = kLastType; + +static const int kBlockSize = 32768; + +// Header is checksum (4 bytes), length (2 bytes), type (1 byte). +static const int kHeaderSize = 4 + 2 + 1; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/log_reader.cc b/MyExperiences copy/Pods/leveldb-library/db/log_reader.cc new file mode 100644 index 00000000..f4727234 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/log_reader.cc @@ -0,0 +1,274 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Reader::Reporter::~Reporter() {} + +Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset) + : file_(file), + reporter_(reporter), + checksum_(checksum), + backing_store_(new char[kBlockSize]), + buffer_(), + eof_(false), + last_record_offset_(0), + end_of_buffer_offset_(0), + initial_offset_(initial_offset), + resyncing_(initial_offset > 0) {} + +Reader::~Reader() { delete[] backing_store_; } + +bool Reader::SkipToInitialBlock() { + const size_t offset_in_block = initial_offset_ % kBlockSize; + uint64_t block_start_location = initial_offset_ - offset_in_block; + + // Don't search a block if we'd be in the trailer + if (offset_in_block > kBlockSize - 6) { + block_start_location += kBlockSize; + } + + end_of_buffer_offset_ = block_start_location; + + // Skip to start of first block that can contain the initial record + if (block_start_location > 0) { + Status skip_status = file_->Skip(block_start_location); + if (!skip_status.ok()) { + ReportDrop(block_start_location, skip_status); + return false; + } + } + + return true; +} + +bool Reader::ReadRecord(Slice* record, std::string* scratch) { + if (last_record_offset_ < initial_offset_) { + if (!SkipToInitialBlock()) { + return false; + } + } + + scratch->clear(); + record->clear(); + bool in_fragmented_record = false; + // Record offset of the logical record that we're reading + // 0 is a dummy value to make compilers happy + uint64_t prospective_record_offset = 0; + + Slice fragment; + while (true) { + const unsigned int record_type = ReadPhysicalRecord(&fragment); + + // ReadPhysicalRecord may have only had an empty trailer remaining in its + // internal buffer. Calculate the offset of the next physical record now + // that it has returned, properly accounting for its header size. + uint64_t physical_record_offset = + end_of_buffer_offset_ - buffer_.size() - kHeaderSize - fragment.size(); + + if (resyncing_) { + if (record_type == kMiddleType) { + continue; + } else if (record_type == kLastType) { + resyncing_ = false; + continue; + } else { + resyncing_ = false; + } + } + + switch (record_type) { + case kFullType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(1)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->clear(); + *record = fragment; + last_record_offset_ = prospective_record_offset; + return true; + + case kFirstType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(2)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->assign(fragment.data(), fragment.size()); + in_fragmented_record = true; + break; + + case kMiddleType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(1)"); + } else { + scratch->append(fragment.data(), fragment.size()); + } + break; + + case kLastType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(2)"); + } else { + scratch->append(fragment.data(), fragment.size()); + *record = Slice(*scratch); + last_record_offset_ = prospective_record_offset; + return true; + } + break; + + case kEof: + if (in_fragmented_record) { + // This can be caused by the writer dying immediately after + // writing a physical record but before completing the next; don't + // treat it as a corruption, just ignore the entire logical record. + scratch->clear(); + } + return false; + + case kBadRecord: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "error in middle of record"); + in_fragmented_record = false; + scratch->clear(); + } + break; + + default: { + char buf[40]; + snprintf(buf, sizeof(buf), "unknown record type %u", record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + buf); + in_fragmented_record = false; + scratch->clear(); + break; + } + } + } + return false; +} + +uint64_t Reader::LastRecordOffset() { return last_record_offset_; } + +void Reader::ReportCorruption(uint64_t bytes, const char* reason) { + ReportDrop(bytes, Status::Corruption(reason)); +} + +void Reader::ReportDrop(uint64_t bytes, const Status& reason) { + if (reporter_ != nullptr && + end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { + reporter_->Corruption(static_cast(bytes), reason); + } +} + +unsigned int Reader::ReadPhysicalRecord(Slice* result) { + while (true) { + if (buffer_.size() < kHeaderSize) { + if (!eof_) { + // Last read was a full read, so this is a trailer to skip + buffer_.clear(); + Status status = file_->Read(kBlockSize, &buffer_, backing_store_); + end_of_buffer_offset_ += buffer_.size(); + if (!status.ok()) { + buffer_.clear(); + ReportDrop(kBlockSize, status); + eof_ = true; + return kEof; + } else if (buffer_.size() < kBlockSize) { + eof_ = true; + } + continue; + } else { + // Note that if buffer_ is non-empty, we have a truncated header at the + // end of the file, which can be caused by the writer crashing in the + // middle of writing the header. Instead of considering this an error, + // just report EOF. + buffer_.clear(); + return kEof; + } + } + + // Parse the header + const char* header = buffer_.data(); + const uint32_t a = static_cast(header[4]) & 0xff; + const uint32_t b = static_cast(header[5]) & 0xff; + const unsigned int type = header[6]; + const uint32_t length = a | (b << 8); + if (kHeaderSize + length > buffer_.size()) { + size_t drop_size = buffer_.size(); + buffer_.clear(); + if (!eof_) { + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + // If the end of the file has been reached without reading |length| bytes + // of payload, assume the writer died in the middle of writing the record. + // Don't report a corruption. + return kEof; + } + + if (type == kZeroType && length == 0) { + // Skip zero length record without reporting any drops since + // such records are produced by the mmap based writing code in + // env_posix.cc that preallocates file regions. + buffer_.clear(); + return kBadRecord; + } + + // Check crc + if (checksum_) { + uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); + uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); + if (actual_crc != expected_crc) { + // Drop the rest of the buffer since "length" itself may have + // been corrupted and if we trust it, we could find some + // fragment of a real log record that just happens to look + // like a valid log record. + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "checksum mismatch"); + return kBadRecord; + } + } + + buffer_.remove_prefix(kHeaderSize + length); + + // Skip physical record that started before initial_offset_ + if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < + initial_offset_) { + result->clear(); + return kBadRecord; + } + + *result = Slice(header + kHeaderSize, length); + return type; + } +} + +} // namespace log +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/log_reader.h b/MyExperiences copy/Pods/leveldb-library/db/log_reader.h new file mode 100644 index 00000000..001da894 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/log_reader.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ +#define STORAGE_LEVELDB_DB_LOG_READER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class SequentialFile; + +namespace log { + +class Reader { + public: + // Interface for reporting errors. + class Reporter { + public: + virtual ~Reporter(); + + // Some corruption was detected. "size" is the approximate number + // of bytes dropped due to the corruption. + virtual void Corruption(size_t bytes, const Status& status) = 0; + }; + + // Create a reader that will return log records from "*file". + // "*file" must remain live while this Reader is in use. + // + // If "reporter" is non-null, it is notified whenever some data is + // dropped due to a detected corruption. "*reporter" must remain + // live while this Reader is in use. + // + // If "checksum" is true, verify checksums if available. + // + // The Reader will start reading at the first record located at physical + // position >= initial_offset within the file. + Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset); + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + ~Reader(); + + // Read the next record into *record. Returns true if read + // successfully, false if we hit end of the input. May use + // "*scratch" as temporary storage. The contents filled in *record + // will only be valid until the next mutating operation on this + // reader or the next mutation to *scratch. + bool ReadRecord(Slice* record, std::string* scratch); + + // Returns the physical offset of the last record returned by ReadRecord. + // + // Undefined before the first call to ReadRecord. + uint64_t LastRecordOffset(); + + private: + // Extend record types with the following special values + enum { + kEof = kMaxRecordType + 1, + // Returned whenever we find an invalid physical record. + // Currently there are three situations in which this happens: + // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) + // * The record is a 0-length record (No drop is reported) + // * The record is below constructor's initial_offset (No drop is reported) + kBadRecord = kMaxRecordType + 2 + }; + + // Skips all blocks that are completely before "initial_offset_". + // + // Returns true on success. Handles reporting. + bool SkipToInitialBlock(); + + // Return type, or one of the preceding special values + unsigned int ReadPhysicalRecord(Slice* result); + + // Reports dropped bytes to the reporter. + // buffer_ must be updated to remove the dropped bytes prior to invocation. + void ReportCorruption(uint64_t bytes, const char* reason); + void ReportDrop(uint64_t bytes, const Status& reason); + + SequentialFile* const file_; + Reporter* const reporter_; + bool const checksum_; + char* const backing_store_; + Slice buffer_; + bool eof_; // Last Read() indicated EOF by returning < kBlockSize + + // Offset of the last record returned by ReadRecord. + uint64_t last_record_offset_; + // Offset of the first location past the end of buffer_. + uint64_t end_of_buffer_offset_; + + // Offset at which to start looking for the first record to return + uint64_t const initial_offset_; + + // True if we are resynchronizing after a seek (initial_offset_ > 0). In + // particular, a run of kMiddleType and kLastType records can be silently + // skipped in this mode + bool resyncing_; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/log_writer.cc b/MyExperiences copy/Pods/leveldb-library/db/log_writer.cc new file mode 100644 index 00000000..5e83f6a2 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/log_writer.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_writer.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +static void InitTypeCrc(uint32_t* type_crc) { + for (int i = 0; i <= kMaxRecordType; i++) { + char t = static_cast(i); + type_crc[i] = crc32c::Value(&t, 1); + } +} + +Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) { + InitTypeCrc(type_crc_); +} + +Writer::Writer(WritableFile* dest, uint64_t dest_length) + : dest_(dest), block_offset_(dest_length % kBlockSize) { + InitTypeCrc(type_crc_); +} + +Writer::~Writer() {} + +Status Writer::AddRecord(const Slice& slice) { + const char* ptr = slice.data(); + size_t left = slice.size(); + + // Fragment the record if necessary and emit it. Note that if slice + // is empty, we still want to iterate once to emit a single + // zero-length record + Status s; + bool begin = true; + do { + const int leftover = kBlockSize - block_offset_; + assert(leftover >= 0); + if (leftover < kHeaderSize) { + // Switch to a new block + if (leftover > 0) { + // Fill the trailer (literal below relies on kHeaderSize being 7) + static_assert(kHeaderSize == 7, ""); + dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); + } + block_offset_ = 0; + } + + // Invariant: we never leave < kHeaderSize bytes in a block. + assert(kBlockSize - block_offset_ - kHeaderSize >= 0); + + const size_t avail = kBlockSize - block_offset_ - kHeaderSize; + const size_t fragment_length = (left < avail) ? left : avail; + + RecordType type; + const bool end = (left == fragment_length); + if (begin && end) { + type = kFullType; + } else if (begin) { + type = kFirstType; + } else if (end) { + type = kLastType; + } else { + type = kMiddleType; + } + + s = EmitPhysicalRecord(type, ptr, fragment_length); + ptr += fragment_length; + left -= fragment_length; + begin = false; + } while (s.ok() && left > 0); + return s; +} + +Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, + size_t length) { + assert(length <= 0xffff); // Must fit in two bytes + assert(block_offset_ + kHeaderSize + length <= kBlockSize); + + // Format the header + char buf[kHeaderSize]; + buf[4] = static_cast(length & 0xff); + buf[5] = static_cast(length >> 8); + buf[6] = static_cast(t); + + // Compute the crc of the record type and the payload. + uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length); + crc = crc32c::Mask(crc); // Adjust for storage + EncodeFixed32(buf, crc); + + // Write the header and the payload + Status s = dest_->Append(Slice(buf, kHeaderSize)); + if (s.ok()) { + s = dest_->Append(Slice(ptr, length)); + if (s.ok()) { + s = dest_->Flush(); + } + } + block_offset_ += kHeaderSize + length; + return s; +} + +} // namespace log +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/log_writer.h b/MyExperiences copy/Pods/leveldb-library/db/log_writer.h new file mode 100644 index 00000000..c0a21147 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/log_writer.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ +#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +namespace log { + +class Writer { + public: + // Create a writer that will append data to "*dest". + // "*dest" must be initially empty. + // "*dest" must remain live while this Writer is in use. + explicit Writer(WritableFile* dest); + + // Create a writer that will append data to "*dest". + // "*dest" must have initial length "dest_length". + // "*dest" must remain live while this Writer is in use. + Writer(WritableFile* dest, uint64_t dest_length); + + Writer(const Writer&) = delete; + Writer& operator=(const Writer&) = delete; + + ~Writer(); + + Status AddRecord(const Slice& slice); + + private: + Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); + + WritableFile* dest_; + int block_offset_; // Current offset in block + + // crc32c values for all supported record types. These are + // pre-computed to reduce the overhead of computing the crc of the + // record type stored in the header. + uint32_t type_crc_[kMaxRecordType + 1]; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/memtable.cc b/MyExperiences copy/Pods/leveldb-library/db/memtable.cc new file mode 100644 index 00000000..c91405c2 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/memtable.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/memtable.h" +#include "db/dbformat.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +static Slice GetLengthPrefixedSlice(const char* data) { + uint32_t len; + const char* p = data; + p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted + return Slice(p, len); +} + +MemTable::MemTable(const InternalKeyComparator& comparator) + : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {} + +MemTable::~MemTable() { assert(refs_ == 0); } + +size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } + +int MemTable::KeyComparator::operator()(const char* aptr, + const char* bptr) const { + // Internal keys are encoded as length-prefixed strings. + Slice a = GetLengthPrefixedSlice(aptr); + Slice b = GetLengthPrefixedSlice(bptr); + return comparator.Compare(a, b); +} + +// Encode a suitable internal key target for "target" and return it. +// Uses *scratch as scratch space, and the returned pointer will point +// into this scratch space. +static const char* EncodeKey(std::string* scratch, const Slice& target) { + scratch->clear(); + PutVarint32(scratch, target.size()); + scratch->append(target.data(), target.size()); + return scratch->data(); +} + +class MemTableIterator : public Iterator { + public: + explicit MemTableIterator(MemTable::Table* table) : iter_(table) {} + + virtual bool Valid() const { return iter_.Valid(); } + virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } + virtual void SeekToFirst() { iter_.SeekToFirst(); } + virtual void SeekToLast() { iter_.SeekToLast(); } + virtual void Next() { iter_.Next(); } + virtual void Prev() { iter_.Prev(); } + virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } + virtual Slice value() const { + Slice key_slice = GetLengthPrefixedSlice(iter_.key()); + return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); + } + + virtual Status status() const { return Status::OK(); } + + private: + MemTable::Table::Iterator iter_; + std::string tmp_; // For passing to EncodeKey + + // No copying allowed + MemTableIterator(const MemTableIterator&); + void operator=(const MemTableIterator&); +}; + +Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); } + +void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, + const Slice& value) { + // Format of an entry is concatenation of: + // key_size : varint32 of internal_key.size() + // key bytes : char[internal_key.size()] + // value_size : varint32 of value.size() + // value bytes : char[value.size()] + size_t key_size = key.size(); + size_t val_size = value.size(); + size_t internal_key_size = key_size + 8; + const size_t encoded_len = VarintLength(internal_key_size) + + internal_key_size + VarintLength(val_size) + + val_size; + char* buf = arena_.Allocate(encoded_len); + char* p = EncodeVarint32(buf, internal_key_size); + memcpy(p, key.data(), key_size); + p += key_size; + EncodeFixed64(p, (s << 8) | type); + p += 8; + p = EncodeVarint32(p, val_size); + memcpy(p, value.data(), val_size); + assert(p + val_size == buf + encoded_len); + table_.Insert(buf); +} + +bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { + Slice memkey = key.memtable_key(); + Table::Iterator iter(&table_); + iter.Seek(memkey.data()); + if (iter.Valid()) { + // entry format is: + // klength varint32 + // userkey char[klength] + // tag uint64 + // vlength varint32 + // value char[vlength] + // Check that it belongs to same user key. We do not check the + // sequence number since the Seek() call above should have skipped + // all entries with overly large sequence numbers. + const char* entry = iter.key(); + uint32_t key_length; + const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); + if (comparator_.comparator.user_comparator()->Compare( + Slice(key_ptr, key_length - 8), key.user_key()) == 0) { + // Correct user key + const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); + switch (static_cast(tag & 0xff)) { + case kTypeValue: { + Slice v = GetLengthPrefixedSlice(key_ptr + key_length); + value->assign(v.data(), v.size()); + return true; + } + case kTypeDeletion: + *s = Status::NotFound(Slice()); + return true; + } + } + } + return false; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/memtable.h b/MyExperiences copy/Pods/leveldb-library/db/memtable.h new file mode 100644 index 00000000..9d986b10 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/memtable.h @@ -0,0 +1,87 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ +#define STORAGE_LEVELDB_DB_MEMTABLE_H_ + +#include + +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "leveldb/db.h" +#include "util/arena.h" + +namespace leveldb { + +class InternalKeyComparator; +class MemTableIterator; + +class MemTable { + public: + // MemTables are reference counted. The initial reference count + // is zero and the caller must call Ref() at least once. + explicit MemTable(const InternalKeyComparator& comparator); + + MemTable(const MemTable&) = delete; + MemTable& operator=(const MemTable&) = delete; + + // Increase reference count. + void Ref() { ++refs_; } + + // Drop reference count. Delete if no more references exist. + void Unref() { + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + delete this; + } + } + + // Returns an estimate of the number of bytes of data in use by this + // data structure. It is safe to call when MemTable is being modified. + size_t ApproximateMemoryUsage(); + + // Return an iterator that yields the contents of the memtable. + // + // The caller must ensure that the underlying MemTable remains live + // while the returned iterator is live. The keys returned by this + // iterator are internal keys encoded by AppendInternalKey in the + // db/format.{h,cc} module. + Iterator* NewIterator(); + + // Add an entry into memtable that maps key to value at the + // specified sequence number and with the specified type. + // Typically value will be empty if type==kTypeDeletion. + void Add(SequenceNumber seq, ValueType type, const Slice& key, + const Slice& value); + + // If memtable contains a value for key, store it in *value and return true. + // If memtable contains a deletion for key, store a NotFound() error + // in *status and return true. + // Else, return false. + bool Get(const LookupKey& key, std::string* value, Status* s); + + private: + friend class MemTableIterator; + friend class MemTableBackwardIterator; + + struct KeyComparator { + const InternalKeyComparator comparator; + explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {} + int operator()(const char* a, const char* b) const; + }; + + typedef SkipList Table; + + ~MemTable(); // Private since only Unref() should be used to delete it + + KeyComparator comparator_; + int refs_; + Arena arena_; + Table table_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/repair.cc b/MyExperiences copy/Pods/leveldb-library/db/repair.cc new file mode 100644 index 00000000..3c676ca3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/repair.cc @@ -0,0 +1,450 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// We recover the contents of the descriptor from the other files we find. +// (1) Any log files are first converted to tables +// (2) We scan every table to compute +// (a) smallest/largest for the table +// (b) largest sequence number in the table +// (3) We generate descriptor contents: +// - log number is set to zero +// - next-file-number is set to 1 + largest file number we found +// - last-sequence-number is set to largest sequence# found across +// all tables (see 2c) +// - compaction pointers are cleared +// - every table file is added at level 0 +// +// Possible optimization 1: +// (a) Compute total size and use to pick appropriate max-level M +// (b) Sort tables by largest sequence# in the table +// (c) For each table: if it overlaps earlier table, place in level-0, +// else place in level-M. +// Possible optimization 2: +// Store per-table metadata (smallest, largest, largest-seq#, ...) +// in the table's meta section to speed up ScanTable. + +#include "db/builder.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" + +namespace leveldb { + +namespace { + +class Repairer { + public: + Repairer(const std::string& dbname, const Options& options) + : dbname_(dbname), + env_(options.env), + icmp_(options.comparator), + ipolicy_(options.filter_policy), + options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), + owns_info_log_(options_.info_log != options.info_log), + owns_cache_(options_.block_cache != options.block_cache), + next_file_number_(1) { + // TableCache can be small since we expect each table to be opened once. + table_cache_ = new TableCache(dbname_, options_, 10); + } + + ~Repairer() { + delete table_cache_; + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } + } + + Status Run() { + Status status = FindFiles(); + if (status.ok()) { + ConvertLogFilesToTables(); + ExtractMetaData(); + status = WriteDescriptor(); + } + if (status.ok()) { + unsigned long long bytes = 0; + for (size_t i = 0; i < tables_.size(); i++) { + bytes += tables_[i].meta.file_size; + } + Log(options_.info_log, + "**** Repaired leveldb %s; " + "recovered %d files; %llu bytes. " + "Some data may have been lost. " + "****", + dbname_.c_str(), static_cast(tables_.size()), bytes); + } + return status; + } + + private: + struct TableInfo { + FileMetaData meta; + SequenceNumber max_sequence; + }; + + Status FindFiles() { + std::vector filenames; + Status status = env_->GetChildren(dbname_, &filenames); + if (!status.ok()) { + return status; + } + if (filenames.empty()) { + return Status::IOError(dbname_, "repair found no files"); + } + + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + if (type == kDescriptorFile) { + manifests_.push_back(filenames[i]); + } else { + if (number + 1 > next_file_number_) { + next_file_number_ = number + 1; + } + if (type == kLogFile) { + logs_.push_back(number); + } else if (type == kTableFile) { + table_numbers_.push_back(number); + } else { + // Ignore other files + } + } + } + } + return status; + } + + void ConvertLogFilesToTables() { + for (size_t i = 0; i < logs_.size(); i++) { + std::string logname = LogFileName(dbname_, logs_[i]); + Status status = ConvertLogToTable(logs_[i]); + if (!status.ok()) { + Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", + (unsigned long long)logs_[i], status.ToString().c_str()); + } + ArchiveFile(logname); + } + } + + Status ConvertLogToTable(uint64_t log) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + uint64_t lognum; + virtual void Corruption(size_t bytes, const Status& s) { + // We print error messages for corruption, but continue repairing. + Log(info_log, "Log #%llu: dropping %d bytes; %s", + (unsigned long long)lognum, static_cast(bytes), + s.ToString().c_str()); + } + }; + + // Open the log file + std::string logname = LogFileName(dbname_, log); + SequentialFile* lfile; + Status status = env_->NewSequentialFile(logname, &lfile); + if (!status.ok()) { + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.lognum = log; + // We intentionally make log::Reader do checksumming so that + // corruptions cause entire commits to be skipped instead of + // propagating bad information (like overly large sequence + // numbers). + log::Reader reader(lfile, &reporter, false /*do not checksum*/, + 0 /*initial_offset*/); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = new MemTable(icmp_); + mem->Ref(); + int counter = 0; + while (reader.ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + status = WriteBatchInternal::InsertInto(&batch, mem); + if (status.ok()) { + counter += WriteBatchInternal::Count(&batch); + } else { + Log(options_.info_log, "Log #%llu: ignoring %s", + (unsigned long long)log, status.ToString().c_str()); + status = Status::OK(); // Keep going with rest of file + } + } + delete lfile; + + // Do not record a version edit for this conversion to a Table + // since ExtractMetaData() will also generate edits. + FileMetaData meta; + meta.number = next_file_number_++; + Iterator* iter = mem->NewIterator(); + status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + delete iter; + mem->Unref(); + mem = nullptr; + if (status.ok()) { + if (meta.file_size > 0) { + table_numbers_.push_back(meta.number); + } + } + Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", + (unsigned long long)log, counter, (unsigned long long)meta.number, + status.ToString().c_str()); + return status; + } + + void ExtractMetaData() { + for (size_t i = 0; i < table_numbers_.size(); i++) { + ScanTable(table_numbers_[i]); + } + } + + Iterator* NewTableIterator(const FileMetaData& meta) { + // Same as compaction iterators: if paranoid_checks are on, turn + // on checksum verification. + ReadOptions r; + r.verify_checksums = options_.paranoid_checks; + return table_cache_->NewIterator(r, meta.number, meta.file_size); + } + + void ScanTable(uint64_t number) { + TableInfo t; + t.meta.number = number; + std::string fname = TableFileName(dbname_, number); + Status status = env_->GetFileSize(fname, &t.meta.file_size); + if (!status.ok()) { + // Try alternate file name. + fname = SSTTableFileName(dbname_, number); + Status s2 = env_->GetFileSize(fname, &t.meta.file_size); + if (s2.ok()) { + status = Status::OK(); + } + } + if (!status.ok()) { + ArchiveFile(TableFileName(dbname_, number)); + ArchiveFile(SSTTableFileName(dbname_, number)); + Log(options_.info_log, "Table #%llu: dropped: %s", + (unsigned long long)t.meta.number, status.ToString().c_str()); + return; + } + + // Extract metadata by scanning through table. + int counter = 0; + Iterator* iter = NewTableIterator(t.meta); + bool empty = true; + ParsedInternalKey parsed; + t.max_sequence = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + if (!ParseInternalKey(key, &parsed)) { + Log(options_.info_log, "Table #%llu: unparsable key %s", + (unsigned long long)t.meta.number, EscapeString(key).c_str()); + continue; + } + + counter++; + if (empty) { + empty = false; + t.meta.smallest.DecodeFrom(key); + } + t.meta.largest.DecodeFrom(key); + if (parsed.sequence > t.max_sequence) { + t.max_sequence = parsed.sequence; + } + } + if (!iter->status().ok()) { + status = iter->status(); + } + delete iter; + Log(options_.info_log, "Table #%llu: %d entries %s", + (unsigned long long)t.meta.number, counter, status.ToString().c_str()); + + if (status.ok()) { + tables_.push_back(t); + } else { + RepairTable(fname, t); // RepairTable archives input file. + } + } + + void RepairTable(const std::string& src, TableInfo t) { + // We will copy src contents to a new table and then rename the + // new table over the source. + + // Create builder. + std::string copy = TableFileName(dbname_, next_file_number_++); + WritableFile* file; + Status s = env_->NewWritableFile(copy, &file); + if (!s.ok()) { + return; + } + TableBuilder* builder = new TableBuilder(options_, file); + + // Copy data. + Iterator* iter = NewTableIterator(t.meta); + int counter = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + builder->Add(iter->key(), iter->value()); + counter++; + } + delete iter; + + ArchiveFile(src); + if (counter == 0) { + builder->Abandon(); // Nothing to save + } else { + s = builder->Finish(); + if (s.ok()) { + t.meta.file_size = builder->FileSize(); + } + } + delete builder; + builder = nullptr; + + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (counter > 0 && s.ok()) { + std::string orig = TableFileName(dbname_, t.meta.number); + s = env_->RenameFile(copy, orig); + if (s.ok()) { + Log(options_.info_log, "Table #%llu: %d entries repaired", + (unsigned long long)t.meta.number, counter); + tables_.push_back(t); + } + } + if (!s.ok()) { + env_->DeleteFile(copy); + } + } + + Status WriteDescriptor() { + std::string tmp = TempFileName(dbname_, 1); + WritableFile* file; + Status status = env_->NewWritableFile(tmp, &file); + if (!status.ok()) { + return status; + } + + SequenceNumber max_sequence = 0; + for (size_t i = 0; i < tables_.size(); i++) { + if (max_sequence < tables_[i].max_sequence) { + max_sequence = tables_[i].max_sequence; + } + } + + edit_.SetComparatorName(icmp_.user_comparator()->Name()); + edit_.SetLogNumber(0); + edit_.SetNextFile(next_file_number_); + edit_.SetLastSequence(max_sequence); + + for (size_t i = 0; i < tables_.size(); i++) { + // TODO(opt): separate out into multiple levels + const TableInfo& t = tables_[i]; + edit_.AddFile(0, t.meta.number, t.meta.file_size, t.meta.smallest, + t.meta.largest); + } + + // fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); + { + log::Writer log(file); + std::string record; + edit_.EncodeTo(&record); + status = log.AddRecord(record); + } + if (status.ok()) { + status = file->Close(); + } + delete file; + file = nullptr; + + if (!status.ok()) { + env_->DeleteFile(tmp); + } else { + // Discard older manifests + for (size_t i = 0; i < manifests_.size(); i++) { + ArchiveFile(dbname_ + "/" + manifests_[i]); + } + + // Install new manifest + status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); + if (status.ok()) { + status = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(tmp); + } + } + return status; + } + + void ArchiveFile(const std::string& fname) { + // Move into another directory. E.g., for + // dir/foo + // rename to + // dir/lost/foo + const char* slash = strrchr(fname.c_str(), '/'); + std::string new_dir; + if (slash != nullptr) { + new_dir.assign(fname.data(), slash - fname.data()); + } + new_dir.append("/lost"); + env_->CreateDir(new_dir); // Ignore error + std::string new_file = new_dir; + new_file.append("/"); + new_file.append((slash == nullptr) ? fname.c_str() : slash + 1); + Status s = env_->RenameFile(fname, new_file); + Log(options_.info_log, "Archiving %s: %s\n", fname.c_str(), + s.ToString().c_str()); + } + + const std::string dbname_; + Env* const env_; + InternalKeyComparator const icmp_; + InternalFilterPolicy const ipolicy_; + const Options options_; + bool owns_info_log_; + bool owns_cache_; + TableCache* table_cache_; + VersionEdit edit_; + + std::vector manifests_; + std::vector table_numbers_; + std::vector logs_; + std::vector tables_; + uint64_t next_file_number_; +}; +} // namespace + +Status RepairDB(const std::string& dbname, const Options& options) { + Repairer repairer(dbname, options); + return repairer.Run(); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/skiplist.h b/MyExperiences copy/Pods/leveldb-library/db/skiplist.h new file mode 100644 index 00000000..a59b45b3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/skiplist.h @@ -0,0 +1,382 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_ +#define STORAGE_LEVELDB_DB_SKIPLIST_H_ + +// Thread safety +// ------------- +// +// Writes require external synchronization, most likely a mutex. +// Reads require a guarantee that the SkipList will not be destroyed +// while the read is in progress. Apart from that, reads progress +// without any internal locking or synchronization. +// +// Invariants: +// +// (1) Allocated nodes are never deleted until the SkipList is +// destroyed. This is trivially guaranteed by the code since we +// never delete any skip list nodes. +// +// (2) The contents of a Node except for the next/prev pointers are +// immutable after the Node has been linked into the SkipList. +// Only Insert() modifies the list, and it is careful to initialize +// a node and use release-stores to publish the nodes in one or +// more lists. +// +// ... prev vs. next pointer ordering ... + +#include +#include +#include + +#include "util/arena.h" +#include "util/random.h" + +namespace leveldb { + +class Arena; + +template +class SkipList { + private: + struct Node; + + public: + // Create a new SkipList object that will use "cmp" for comparing keys, + // and will allocate memory using "*arena". Objects allocated in the arena + // must remain allocated for the lifetime of the skiplist object. + explicit SkipList(Comparator cmp, Arena* arena); + + SkipList(const SkipList&) = delete; + SkipList& operator=(const SkipList&) = delete; + + // Insert key into the list. + // REQUIRES: nothing that compares equal to key is currently in the list. + void Insert(const Key& key); + + // Returns true iff an entry that compares equal to key is in the list. + bool Contains(const Key& key) const; + + // Iteration over the contents of a skip list + class Iterator { + public: + // Initialize an iterator over the specified list. + // The returned iterator is not valid. + explicit Iterator(const SkipList* list); + + // Returns true iff the iterator is positioned at a valid node. + bool Valid() const; + + // Returns the key at the current position. + // REQUIRES: Valid() + const Key& key() const; + + // Advances to the next position. + // REQUIRES: Valid() + void Next(); + + // Advances to the previous position. + // REQUIRES: Valid() + void Prev(); + + // Advance to the first entry with a key >= target + void Seek(const Key& target); + + // Position at the first entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToFirst(); + + // Position at the last entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToLast(); + + private: + const SkipList* list_; + Node* node_; + // Intentionally copyable + }; + + private: + enum { kMaxHeight = 12 }; + + inline int GetMaxHeight() const { + return max_height_.load(std::memory_order_relaxed); + } + + Node* NewNode(const Key& key, int height); + int RandomHeight(); + bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } + + // Return true if key is greater than the data stored in "n" + bool KeyIsAfterNode(const Key& key, Node* n) const; + + // Return the earliest node that comes at or after key. + // Return nullptr if there is no such node. + // + // If prev is non-null, fills prev[level] with pointer to previous + // node at "level" for every level in [0..max_height_-1]. + Node* FindGreaterOrEqual(const Key& key, Node** prev) const; + + // Return the latest node with a key < key. + // Return head_ if there is no such node. + Node* FindLessThan(const Key& key) const; + + // Return the last node in the list. + // Return head_ if list is empty. + Node* FindLast() const; + + // Immutable after construction + Comparator const compare_; + Arena* const arena_; // Arena used for allocations of nodes + + Node* const head_; + + // Modified only by Insert(). Read racily by readers, but stale + // values are ok. + std::atomic max_height_; // Height of the entire list + + // Read/written only by Insert(). + Random rnd_; +}; + +// Implementation details follow +template +struct SkipList::Node { + explicit Node(const Key& k) : key(k) {} + + Key const key; + + // Accessors/mutators for links. Wrapped in methods so we can + // add the appropriate barriers as necessary. + Node* Next(int n) { + assert(n >= 0); + // Use an 'acquire load' so that we observe a fully initialized + // version of the returned Node. + return next_[n].load(std::memory_order_acquire); + } + void SetNext(int n, Node* x) { + assert(n >= 0); + // Use a 'release store' so that anybody who reads through this + // pointer observes a fully initialized version of the inserted node. + next_[n].store(x, std::memory_order_release); + } + + // No-barrier variants that can be safely used in a few locations. + Node* NoBarrier_Next(int n) { + assert(n >= 0); + return next_[n].load(std::memory_order_relaxed); + } + void NoBarrier_SetNext(int n, Node* x) { + assert(n >= 0); + next_[n].store(x, std::memory_order_relaxed); + } + + private: + // Array of length equal to the node height. next_[0] is lowest level link. + std::atomic next_[1]; +}; + +template +typename SkipList::Node* SkipList::NewNode( + const Key& key, int height) { + char* const node_memory = arena_->AllocateAligned( + sizeof(Node) + sizeof(std::atomic) * (height - 1)); + return new (node_memory) Node(key); +} + +template +inline SkipList::Iterator::Iterator(const SkipList* list) { + list_ = list; + node_ = nullptr; +} + +template +inline bool SkipList::Iterator::Valid() const { + return node_ != nullptr; +} + +template +inline const Key& SkipList::Iterator::key() const { + assert(Valid()); + return node_->key; +} + +template +inline void SkipList::Iterator::Next() { + assert(Valid()); + node_ = node_->Next(0); +} + +template +inline void SkipList::Iterator::Prev() { + // Instead of using explicit "prev" links, we just search for the + // last node that falls before key. + assert(Valid()); + node_ = list_->FindLessThan(node_->key); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +inline void SkipList::Iterator::Seek(const Key& target) { + node_ = list_->FindGreaterOrEqual(target, nullptr); +} + +template +inline void SkipList::Iterator::SeekToFirst() { + node_ = list_->head_->Next(0); +} + +template +inline void SkipList::Iterator::SeekToLast() { + node_ = list_->FindLast(); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +int SkipList::RandomHeight() { + // Increase height with probability 1 in kBranching + static const unsigned int kBranching = 4; + int height = 1; + while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { + height++; + } + assert(height > 0); + assert(height <= kMaxHeight); + return height; +} + +template +bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { + // null n is considered infinite + return (n != nullptr) && (compare_(n->key, key) < 0); +} + +template +typename SkipList::Node* +SkipList::FindGreaterOrEqual(const Key& key, + Node** prev) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (KeyIsAfterNode(key, next)) { + // Keep searching in this list + x = next; + } else { + if (prev != nullptr) prev[level] = x; + if (level == 0) { + return next; + } else { + // Switch to next list + level--; + } + } + } +} + +template +typename SkipList::Node* +SkipList::FindLessThan(const Key& key) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + assert(x == head_ || compare_(x->key, key) < 0); + Node* next = x->Next(level); + if (next == nullptr || compare_(next->key, key) >= 0) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +typename SkipList::Node* SkipList::FindLast() + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (next == nullptr) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +SkipList::SkipList(Comparator cmp, Arena* arena) + : compare_(cmp), + arena_(arena), + head_(NewNode(0 /* any key will do */, kMaxHeight)), + max_height_(1), + rnd_(0xdeadbeef) { + for (int i = 0; i < kMaxHeight; i++) { + head_->SetNext(i, nullptr); + } +} + +template +void SkipList::Insert(const Key& key) { + // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() + // here since Insert() is externally synchronized. + Node* prev[kMaxHeight]; + Node* x = FindGreaterOrEqual(key, prev); + + // Our data structure does not allow duplicate insertion + assert(x == nullptr || !Equal(key, x->key)); + + int height = RandomHeight(); + if (height > GetMaxHeight()) { + for (int i = GetMaxHeight(); i < height; i++) { + prev[i] = head_; + } + // It is ok to mutate max_height_ without any synchronization + // with concurrent readers. A concurrent reader that observes + // the new value of max_height_ will see either the old value of + // new level pointers from head_ (nullptr), or a new value set in + // the loop below. In the former case the reader will + // immediately drop to the next level since nullptr sorts after all + // keys. In the latter case the reader will use the new node. + max_height_.store(height, std::memory_order_relaxed); + } + + x = NewNode(key, height); + for (int i = 0; i < height; i++) { + // NoBarrier_SetNext() suffices since we will add a barrier when + // we publish a pointer to "x" in prev[i]. + x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); + prev[i]->SetNext(i, x); + } +} + +template +bool SkipList::Contains(const Key& key) const { + Node* x = FindGreaterOrEqual(key, nullptr); + if (x != nullptr && Equal(key, x->key)) { + return true; + } else { + return false; + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/snapshot.h b/MyExperiences copy/Pods/leveldb-library/db/snapshot.h new file mode 100644 index 00000000..9f1d6649 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/snapshot.h @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ +#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class SnapshotList; + +// Snapshots are kept in a doubly-linked list in the DB. +// Each SnapshotImpl corresponds to a particular sequence number. +class SnapshotImpl : public Snapshot { + public: + SnapshotImpl(SequenceNumber sequence_number) + : sequence_number_(sequence_number) {} + + SequenceNumber sequence_number() const { return sequence_number_; } + + private: + friend class SnapshotList; + + // SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList + // implementation operates on the next/previous fields direcly. + SnapshotImpl* prev_; + SnapshotImpl* next_; + + const SequenceNumber sequence_number_; + +#if !defined(NDEBUG) + SnapshotList* list_ = nullptr; +#endif // !defined(NDEBUG) +}; + +class SnapshotList { + public: + SnapshotList() : head_(0) { + head_.prev_ = &head_; + head_.next_ = &head_; + } + + bool empty() const { return head_.next_ == &head_; } + SnapshotImpl* oldest() const { + assert(!empty()); + return head_.next_; + } + SnapshotImpl* newest() const { + assert(!empty()); + return head_.prev_; + } + + // Creates a SnapshotImpl and appends it to the end of the list. + SnapshotImpl* New(SequenceNumber sequence_number) { + assert(empty() || newest()->sequence_number_ <= sequence_number); + + SnapshotImpl* snapshot = new SnapshotImpl(sequence_number); + +#if !defined(NDEBUG) + snapshot->list_ = this; +#endif // !defined(NDEBUG) + snapshot->next_ = &head_; + snapshot->prev_ = head_.prev_; + snapshot->prev_->next_ = snapshot; + snapshot->next_->prev_ = snapshot; + return snapshot; + } + + // Removes a SnapshotImpl from this list. + // + // The snapshot must have been created by calling New() on this list. + // + // The snapshot pointer should not be const, because its memory is + // deallocated. However, that would force us to change DB::ReleaseSnapshot(), + // which is in the API, and currently takes a const Snapshot. + void Delete(const SnapshotImpl* snapshot) { +#if !defined(NDEBUG) + assert(snapshot->list_ == this); +#endif // !defined(NDEBUG) + snapshot->prev_->next_ = snapshot->next_; + snapshot->next_->prev_ = snapshot->prev_; + delete snapshot; + } + + private: + // Dummy head of doubly-linked list of snapshots + SnapshotImpl head_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/table_cache.cc b/MyExperiences copy/Pods/leveldb-library/db/table_cache.cc new file mode 100644 index 00000000..73f05fd7 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/table_cache.cc @@ -0,0 +1,120 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/table_cache.h" + +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/coding.h" + +namespace leveldb { + +struct TableAndFile { + RandomAccessFile* file; + Table* table; +}; + +static void DeleteEntry(const Slice& key, void* value) { + TableAndFile* tf = reinterpret_cast(value); + delete tf->table; + delete tf->file; + delete tf; +} + +static void UnrefEntry(void* arg1, void* arg2) { + Cache* cache = reinterpret_cast(arg1); + Cache::Handle* h = reinterpret_cast(arg2); + cache->Release(h); +} + +TableCache::TableCache(const std::string& dbname, const Options& options, + int entries) + : env_(options.env), + dbname_(dbname), + options_(options), + cache_(NewLRUCache(entries)) {} + +TableCache::~TableCache() { delete cache_; } + +Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, + Cache::Handle** handle) { + Status s; + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + Slice key(buf, sizeof(buf)); + *handle = cache_->Lookup(key); + if (*handle == nullptr) { + std::string fname = TableFileName(dbname_, file_number); + RandomAccessFile* file = nullptr; + Table* table = nullptr; + s = env_->NewRandomAccessFile(fname, &file); + if (!s.ok()) { + std::string old_fname = SSTTableFileName(dbname_, file_number); + if (env_->NewRandomAccessFile(old_fname, &file).ok()) { + s = Status::OK(); + } + } + if (s.ok()) { + s = Table::Open(options_, file, file_size, &table); + } + + if (!s.ok()) { + assert(table == nullptr); + delete file; + // We do not cache error results so that if the error is transient, + // or somebody repairs the file, we recover automatically. + } else { + TableAndFile* tf = new TableAndFile; + tf->file = file; + tf->table = table; + *handle = cache_->Insert(key, tf, 1, &DeleteEntry); + } + } + return s; +} + +Iterator* TableCache::NewIterator(const ReadOptions& options, + uint64_t file_number, uint64_t file_size, + Table** tableptr) { + if (tableptr != nullptr) { + *tableptr = nullptr; + } + + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (!s.ok()) { + return NewErrorIterator(s); + } + + Table* table = reinterpret_cast(cache_->Value(handle))->table; + Iterator* result = table->NewIterator(options); + result->RegisterCleanup(&UnrefEntry, cache_, handle); + if (tableptr != nullptr) { + *tableptr = table; + } + return result; +} + +Status TableCache::Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (s.ok()) { + Table* t = reinterpret_cast(cache_->Value(handle))->table; + s = t->InternalGet(options, k, arg, handle_result); + cache_->Release(handle); + } + return s; +} + +void TableCache::Evict(uint64_t file_number) { + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + cache_->Erase(Slice(buf, sizeof(buf))); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/table_cache.h b/MyExperiences copy/Pods/leveldb-library/db/table_cache.h new file mode 100644 index 00000000..93069c88 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/table_cache.h @@ -0,0 +1,58 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread-safe (provides internal synchronization) + +#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ +#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ + +#include + +#include + +#include "db/dbformat.h" +#include "leveldb/cache.h" +#include "leveldb/table.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +class TableCache { + public: + TableCache(const std::string& dbname, const Options& options, int entries); + ~TableCache(); + + // Return an iterator for the specified file number (the corresponding + // file length must be exactly "file_size" bytes). If "tableptr" is + // non-null, also sets "*tableptr" to point to the Table object + // underlying the returned iterator, or to nullptr if no Table object + // underlies the returned iterator. The returned "*tableptr" object is owned + // by the cache and should not be deleted, and is valid for as long as the + // returned iterator is live. + Iterator* NewIterator(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, Table** tableptr = nullptr); + + // If a seek to internal key "k" in specified file finds an entry, + // call (*handle_result)(arg, found_key, found_value). + Status Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, const Slice&)); + + // Evict any entry for the specified file number + void Evict(uint64_t file_number); + + private: + Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); + + Env* const env_; + const std::string dbname_; + const Options& options_; + Cache* cache_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/version_edit.cc b/MyExperiences copy/Pods/leveldb-library/db/version_edit.cc new file mode 100644 index 00000000..44a4d022 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/version_edit.cc @@ -0,0 +1,260 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" + +#include "db/version_set.h" +#include "util/coding.h" + +namespace leveldb { + +// Tag numbers for serialized VersionEdit. These numbers are written to +// disk and should not be changed. +enum Tag { + kComparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, + // 8 was used for large value refs + kPrevLogNumber = 9 +}; + +void VersionEdit::Clear() { + comparator_.clear(); + log_number_ = 0; + prev_log_number_ = 0; + last_sequence_ = 0; + next_file_number_ = 0; + has_comparator_ = false; + has_log_number_ = false; + has_prev_log_number_ = false; + has_next_file_number_ = false; + has_last_sequence_ = false; + deleted_files_.clear(); + new_files_.clear(); +} + +void VersionEdit::EncodeTo(std::string* dst) const { + if (has_comparator_) { + PutVarint32(dst, kComparator); + PutLengthPrefixedSlice(dst, comparator_); + } + if (has_log_number_) { + PutVarint32(dst, kLogNumber); + PutVarint64(dst, log_number_); + } + if (has_prev_log_number_) { + PutVarint32(dst, kPrevLogNumber); + PutVarint64(dst, prev_log_number_); + } + if (has_next_file_number_) { + PutVarint32(dst, kNextFileNumber); + PutVarint64(dst, next_file_number_); + } + if (has_last_sequence_) { + PutVarint32(dst, kLastSequence); + PutVarint64(dst, last_sequence_); + } + + for (size_t i = 0; i < compact_pointers_.size(); i++) { + PutVarint32(dst, kCompactPointer); + PutVarint32(dst, compact_pointers_[i].first); // level + PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); + } + + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + PutVarint32(dst, kDeletedFile); + PutVarint32(dst, iter->first); // level + PutVarint64(dst, iter->second); // file number + } + + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + PutVarint32(dst, kNewFile); + PutVarint32(dst, new_files_[i].first); // level + PutVarint64(dst, f.number); + PutVarint64(dst, f.file_size); + PutLengthPrefixedSlice(dst, f.smallest.Encode()); + PutLengthPrefixedSlice(dst, f.largest.Encode()); + } +} + +static bool GetInternalKey(Slice* input, InternalKey* dst) { + Slice str; + if (GetLengthPrefixedSlice(input, &str)) { + dst->DecodeFrom(str); + return true; + } else { + return false; + } +} + +static bool GetLevel(Slice* input, int* level) { + uint32_t v; + if (GetVarint32(input, &v) && v < config::kNumLevels) { + *level = v; + return true; + } else { + return false; + } +} + +Status VersionEdit::DecodeFrom(const Slice& src) { + Clear(); + Slice input = src; + const char* msg = nullptr; + uint32_t tag; + + // Temporary storage for parsing + int level; + uint64_t number; + FileMetaData f; + Slice str; + InternalKey key; + + while (msg == nullptr && GetVarint32(&input, &tag)) { + switch (tag) { + case kComparator: + if (GetLengthPrefixedSlice(&input, &str)) { + comparator_ = str.ToString(); + has_comparator_ = true; + } else { + msg = "comparator name"; + } + break; + + case kLogNumber: + if (GetVarint64(&input, &log_number_)) { + has_log_number_ = true; + } else { + msg = "log number"; + } + break; + + case kPrevLogNumber: + if (GetVarint64(&input, &prev_log_number_)) { + has_prev_log_number_ = true; + } else { + msg = "previous log number"; + } + break; + + case kNextFileNumber: + if (GetVarint64(&input, &next_file_number_)) { + has_next_file_number_ = true; + } else { + msg = "next file number"; + } + break; + + case kLastSequence: + if (GetVarint64(&input, &last_sequence_)) { + has_last_sequence_ = true; + } else { + msg = "last sequence number"; + } + break; + + case kCompactPointer: + if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) { + compact_pointers_.push_back(std::make_pair(level, key)); + } else { + msg = "compaction pointer"; + } + break; + + case kDeletedFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &number)) { + deleted_files_.insert(std::make_pair(level, number)); + } else { + msg = "deleted file"; + } + break; + + case kNewFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) && + GetVarint64(&input, &f.file_size) && + GetInternalKey(&input, &f.smallest) && + GetInternalKey(&input, &f.largest)) { + new_files_.push_back(std::make_pair(level, f)); + } else { + msg = "new-file entry"; + } + break; + + default: + msg = "unknown tag"; + break; + } + } + + if (msg == nullptr && !input.empty()) { + msg = "invalid tag"; + } + + Status result; + if (msg != nullptr) { + result = Status::Corruption("VersionEdit", msg); + } + return result; +} + +std::string VersionEdit::DebugString() const { + std::string r; + r.append("VersionEdit {"); + if (has_comparator_) { + r.append("\n Comparator: "); + r.append(comparator_); + } + if (has_log_number_) { + r.append("\n LogNumber: "); + AppendNumberTo(&r, log_number_); + } + if (has_prev_log_number_) { + r.append("\n PrevLogNumber: "); + AppendNumberTo(&r, prev_log_number_); + } + if (has_next_file_number_) { + r.append("\n NextFile: "); + AppendNumberTo(&r, next_file_number_); + } + if (has_last_sequence_) { + r.append("\n LastSeq: "); + AppendNumberTo(&r, last_sequence_); + } + for (size_t i = 0; i < compact_pointers_.size(); i++) { + r.append("\n CompactPointer: "); + AppendNumberTo(&r, compact_pointers_[i].first); + r.append(" "); + r.append(compact_pointers_[i].second.DebugString()); + } + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + r.append("\n DeleteFile: "); + AppendNumberTo(&r, iter->first); + r.append(" "); + AppendNumberTo(&r, iter->second); + } + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + r.append("\n AddFile: "); + AppendNumberTo(&r, new_files_[i].first); + r.append(" "); + AppendNumberTo(&r, f.number); + r.append(" "); + AppendNumberTo(&r, f.file_size); + r.append(" "); + r.append(f.smallest.DebugString()); + r.append(" .. "); + r.append(f.largest.DebugString()); + } + r.append("\n}\n"); + return r; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/version_edit.h b/MyExperiences copy/Pods/leveldb-library/db/version_edit.h new file mode 100644 index 00000000..2dadda75 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/version_edit.h @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ +#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ + +#include +#include +#include + +#include "db/dbformat.h" + +namespace leveldb { + +class VersionSet; + +struct FileMetaData { + FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) {} + + int refs; + int allowed_seeks; // Seeks allowed until compaction + uint64_t number; + uint64_t file_size; // File size in bytes + InternalKey smallest; // Smallest internal key served by table + InternalKey largest; // Largest internal key served by table +}; + +class VersionEdit { + public: + VersionEdit() { Clear(); } + ~VersionEdit() {} + + void Clear(); + + void SetComparatorName(const Slice& name) { + has_comparator_ = true; + comparator_ = name.ToString(); + } + void SetLogNumber(uint64_t num) { + has_log_number_ = true; + log_number_ = num; + } + void SetPrevLogNumber(uint64_t num) { + has_prev_log_number_ = true; + prev_log_number_ = num; + } + void SetNextFile(uint64_t num) { + has_next_file_number_ = true; + next_file_number_ = num; + } + void SetLastSequence(SequenceNumber seq) { + has_last_sequence_ = true; + last_sequence_ = seq; + } + void SetCompactPointer(int level, const InternalKey& key) { + compact_pointers_.push_back(std::make_pair(level, key)); + } + + // Add the specified file at the specified number. + // REQUIRES: This version has not been saved (see VersionSet::SaveTo) + // REQUIRES: "smallest" and "largest" are smallest and largest keys in file + void AddFile(int level, uint64_t file, uint64_t file_size, + const InternalKey& smallest, const InternalKey& largest) { + FileMetaData f; + f.number = file; + f.file_size = file_size; + f.smallest = smallest; + f.largest = largest; + new_files_.push_back(std::make_pair(level, f)); + } + + // Delete the specified "file" from the specified "level". + void DeleteFile(int level, uint64_t file) { + deleted_files_.insert(std::make_pair(level, file)); + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(const Slice& src); + + std::string DebugString() const; + + private: + friend class VersionSet; + + typedef std::set > DeletedFileSet; + + std::string comparator_; + uint64_t log_number_; + uint64_t prev_log_number_; + uint64_t next_file_number_; + SequenceNumber last_sequence_; + bool has_comparator_; + bool has_log_number_; + bool has_prev_log_number_; + bool has_next_file_number_; + bool has_last_sequence_; + + std::vector > compact_pointers_; + DeletedFileSet deleted_files_; + std::vector > new_files_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/version_set.cc b/MyExperiences copy/Pods/leveldb-library/db/version_set.cc new file mode 100644 index 00000000..96a92cce --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/version_set.cc @@ -0,0 +1,1585 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include + +#include + +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +static size_t TargetFileSize(const Options* options) { + return options->max_file_size; +} + +// Maximum bytes of overlaps in grandparent (i.e., level+2) before we +// stop building a single file in a level->level+1 compaction. +static int64_t MaxGrandParentOverlapBytes(const Options* options) { + return 10 * TargetFileSize(options); +} + +// Maximum number of bytes in all compacted files. We avoid expanding +// the lower level file set of a compaction if it would make the +// total compaction cover more than this many bytes. +static int64_t ExpandedCompactionByteSizeLimit(const Options* options) { + return 25 * TargetFileSize(options); +} + +static double MaxBytesForLevel(const Options* options, int level) { + // Note: the result for level zero is not really used since we set + // the level-0 compaction threshold based on number of files. + + // Result for both level-0 and level-1 + double result = 10. * 1048576.0; + while (level > 1) { + result *= 10; + level--; + } + return result; +} + +static uint64_t MaxFileSizeForLevel(const Options* options, int level) { + // We could vary per level to reduce number of files? + return TargetFileSize(options); +} + +static int64_t TotalFileSize(const std::vector& files) { + int64_t sum = 0; + for (size_t i = 0; i < files.size(); i++) { + sum += files[i]->file_size; + } + return sum; +} + +Version::~Version() { + assert(refs_ == 0); + + // Remove from linked list + prev_->next_ = next_; + next_->prev_ = prev_; + + // Drop references to files + for (int level = 0; level < config::kNumLevels; level++) { + for (size_t i = 0; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + assert(f->refs > 0); + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } +} + +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key) { + uint32_t left = 0; + uint32_t right = files.size(); + while (left < right) { + uint32_t mid = (left + right) / 2; + const FileMetaData* f = files[mid]; + if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { + // Key at "mid.largest" is < "target". Therefore all + // files at or before "mid" are uninteresting. + left = mid + 1; + } else { + // Key at "mid.largest" is >= "target". Therefore all files + // after "mid" are uninteresting. + right = mid; + } + } + return right; +} + +static bool AfterFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs before all keys and is therefore never after *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->largest.user_key()) > 0); +} + +static bool BeforeFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs after all keys and is therefore never before *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->smallest.user_key()) < 0); +} + +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + const Comparator* ucmp = icmp.user_comparator(); + if (!disjoint_sorted_files) { + // Need to check against all files + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + if (AfterFile(ucmp, smallest_user_key, f) || + BeforeFile(ucmp, largest_user_key, f)) { + // No overlap + } else { + return true; // Overlap + } + } + return false; + } + + // Binary search over file list + uint32_t index = 0; + if (smallest_user_key != nullptr) { + // Find the earliest possible internal key for smallest_user_key + InternalKey small_key(*smallest_user_key, kMaxSequenceNumber, + kValueTypeForSeek); + index = FindFile(icmp, files, small_key.Encode()); + } + + if (index >= files.size()) { + // beginning of range is after all files, so no overlap. + return false; + } + + return !BeforeFile(ucmp, largest_user_key, files[index]); +} + +// An internal iterator. For a given version/level pair, yields +// information about the files in the level. For a given entry, key() +// is the largest key that occurs in the file, and value() is an +// 16-byte value containing the file number and file size, both +// encoded using EncodeFixed64. +class Version::LevelFileNumIterator : public Iterator { + public: + LevelFileNumIterator(const InternalKeyComparator& icmp, + const std::vector* flist) + : icmp_(icmp), flist_(flist), index_(flist->size()) { // Marks as invalid + } + virtual bool Valid() const { return index_ < flist_->size(); } + virtual void Seek(const Slice& target) { + index_ = FindFile(icmp_, *flist_, target); + } + virtual void SeekToFirst() { index_ = 0; } + virtual void SeekToLast() { + index_ = flist_->empty() ? 0 : flist_->size() - 1; + } + virtual void Next() { + assert(Valid()); + index_++; + } + virtual void Prev() { + assert(Valid()); + if (index_ == 0) { + index_ = flist_->size(); // Marks as invalid + } else { + index_--; + } + } + Slice key() const { + assert(Valid()); + return (*flist_)[index_]->largest.Encode(); + } + Slice value() const { + assert(Valid()); + EncodeFixed64(value_buf_, (*flist_)[index_]->number); + EncodeFixed64(value_buf_ + 8, (*flist_)[index_]->file_size); + return Slice(value_buf_, sizeof(value_buf_)); + } + virtual Status status() const { return Status::OK(); } + + private: + const InternalKeyComparator icmp_; + const std::vector* const flist_; + uint32_t index_; + + // Backing store for value(). Holds the file number and size. + mutable char value_buf_[16]; +}; + +static Iterator* GetFileIterator(void* arg, const ReadOptions& options, + const Slice& file_value) { + TableCache* cache = reinterpret_cast(arg); + if (file_value.size() != 16) { + return NewErrorIterator( + Status::Corruption("FileReader invoked with unexpected value")); + } else { + return cache->NewIterator(options, DecodeFixed64(file_value.data()), + DecodeFixed64(file_value.data() + 8)); + } +} + +Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, + int level) const { + return NewTwoLevelIterator( + new LevelFileNumIterator(vset_->icmp_, &files_[level]), &GetFileIterator, + vset_->table_cache_, options); +} + +void Version::AddIterators(const ReadOptions& options, + std::vector* iters) { + // Merge all level zero files together since they may overlap + for (size_t i = 0; i < files_[0].size(); i++) { + iters->push_back(vset_->table_cache_->NewIterator( + options, files_[0][i]->number, files_[0][i]->file_size)); + } + + // For levels > 0, we can use a concatenating iterator that sequentially + // walks through the non-overlapping files in the level, opening them + // lazily. + for (int level = 1; level < config::kNumLevels; level++) { + if (!files_[level].empty()) { + iters->push_back(NewConcatenatingIterator(options, level)); + } + } +} + +// Callback from TableCache::Get() +namespace { +enum SaverState { + kNotFound, + kFound, + kDeleted, + kCorrupt, +}; +struct Saver { + SaverState state; + const Comparator* ucmp; + Slice user_key; + std::string* value; +}; +} // namespace +static void SaveValue(void* arg, const Slice& ikey, const Slice& v) { + Saver* s = reinterpret_cast(arg); + ParsedInternalKey parsed_key; + if (!ParseInternalKey(ikey, &parsed_key)) { + s->state = kCorrupt; + } else { + if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { + s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; + if (s->state == kFound) { + s->value->assign(v.data(), v.size()); + } + } + } +} + +static bool NewestFirst(FileMetaData* a, FileMetaData* b) { + return a->number > b->number; +} + +void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)) { + // TODO(sanjay): Change Version::Get() to use this function. + const Comparator* ucmp = vset_->icmp_.user_comparator(); + + // Search level-0 in order from newest to oldest. + std::vector tmp; + tmp.reserve(files_[0].size()); + for (uint32_t i = 0; i < files_[0].size(); i++) { + FileMetaData* f = files_[0][i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (!tmp.empty()) { + std::sort(tmp.begin(), tmp.end(), NewestFirst); + for (uint32_t i = 0; i < tmp.size(); i++) { + if (!(*func)(arg, 0, tmp[i])) { + return; + } + } + } + + // Search other levels. + for (int level = 1; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Binary search to find earliest index whose largest key >= internal_key. + uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); + if (index < num_files) { + FileMetaData* f = files_[level][index]; + if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { + // All of "f" is past any data for user_key + } else { + if (!(*func)(arg, level, f)) { + return; + } + } + } + } +} + +Status Version::Get(const ReadOptions& options, const LookupKey& k, + std::string* value, GetStats* stats) { + Slice ikey = k.internal_key(); + Slice user_key = k.user_key(); + const Comparator* ucmp = vset_->icmp_.user_comparator(); + Status s; + + stats->seek_file = nullptr; + stats->seek_file_level = -1; + FileMetaData* last_file_read = nullptr; + int last_file_read_level = -1; + + // We can search level-by-level since entries never hop across + // levels. Therefore we are guaranteed that if we find data + // in a smaller level, later levels are irrelevant. + std::vector tmp; + FileMetaData* tmp2; + for (int level = 0; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Get the list of files to search in this level + FileMetaData* const* files = &files_[level][0]; + if (level == 0) { + // Level-0 files may overlap each other. Find all files that + // overlap user_key and process them in order from newest to oldest. + tmp.reserve(num_files); + for (uint32_t i = 0; i < num_files; i++) { + FileMetaData* f = files[i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (tmp.empty()) continue; + + std::sort(tmp.begin(), tmp.end(), NewestFirst); + files = &tmp[0]; + num_files = tmp.size(); + } else { + // Binary search to find earliest index whose largest key >= ikey. + uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); + if (index >= num_files) { + files = nullptr; + num_files = 0; + } else { + tmp2 = files[index]; + if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { + // All of "tmp2" is past any data for user_key + files = nullptr; + num_files = 0; + } else { + files = &tmp2; + num_files = 1; + } + } + } + + for (uint32_t i = 0; i < num_files; ++i) { + if (last_file_read != nullptr && stats->seek_file == nullptr) { + // We have had more than one seek for this read. Charge the 1st file. + stats->seek_file = last_file_read; + stats->seek_file_level = last_file_read_level; + } + + FileMetaData* f = files[i]; + last_file_read = f; + last_file_read_level = level; + + Saver saver; + saver.state = kNotFound; + saver.ucmp = ucmp; + saver.user_key = user_key; + saver.value = value; + s = vset_->table_cache_->Get(options, f->number, f->file_size, ikey, + &saver, SaveValue); + if (!s.ok()) { + return s; + } + switch (saver.state) { + case kNotFound: + break; // Keep searching in other files + case kFound: + return s; + case kDeleted: + s = Status::NotFound(Slice()); // Use empty error message for speed + return s; + case kCorrupt: + s = Status::Corruption("corrupted key for ", user_key); + return s; + } + } + } + + return Status::NotFound(Slice()); // Use an empty error message for speed +} + +bool Version::UpdateStats(const GetStats& stats) { + FileMetaData* f = stats.seek_file; + if (f != nullptr) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } + } + return false; +} + +bool Version::RecordReadSample(Slice internal_key) { + ParsedInternalKey ikey; + if (!ParseInternalKey(internal_key, &ikey)) { + return false; + } + + struct State { + GetStats stats; // Holds first matching file + int matches; + + static bool Match(void* arg, int level, FileMetaData* f) { + State* state = reinterpret_cast(arg); + state->matches++; + if (state->matches == 1) { + // Remember first match. + state->stats.seek_file = f; + state->stats.seek_file_level = level; + } + // We can stop iterating once we have a second match. + return state->matches < 2; + } + }; + + State state; + state.matches = 0; + ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match); + + // Must have at least two matches since we want to merge across + // files. But what if we have a single file that contains many + // overwrites and deletions? Should we have another mechanism for + // finding such files? + if (state.matches >= 2) { + // 1MB cost is about 1 seek (see comment in Builder::Apply). + return UpdateStats(state.stats); + } + return false; +} + +void Version::Ref() { ++refs_; } + +void Version::Unref() { + assert(this != &vset_->dummy_versions_); + assert(refs_ >= 1); + --refs_; + if (refs_ == 0) { + delete this; + } +} + +bool Version::OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key) { + return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], + smallest_user_key, largest_user_key); +} + +int Version::PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key) { + int level = 0; + if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { + // Push to next level if there is no overlap in next level, + // and the #bytes overlapping in the level after that are limited. + InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey limit(largest_user_key, 0, static_cast(0)); + std::vector overlaps; + while (level < config::kMaxMemCompactLevel) { + if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { + break; + } + if (level + 2 < config::kNumLevels) { + // Check that file does not overlap too many grandparent bytes. + GetOverlappingInputs(level + 2, &start, &limit, &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > MaxGrandParentOverlapBytes(vset_->options_)) { + break; + } + } + level++; + } + } + return level; +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +void Version::GetOverlappingInputs(int level, const InternalKey* begin, + const InternalKey* end, + std::vector* inputs) { + assert(level >= 0); + assert(level < config::kNumLevels); + inputs->clear(); + Slice user_begin, user_end; + if (begin != nullptr) { + user_begin = begin->user_key(); + } + if (end != nullptr) { + user_end = end->user_key(); + } + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + for (size_t i = 0; i < files_[level].size();) { + FileMetaData* f = files_[level][i++]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (begin != nullptr && user_cmp->Compare(file_limit, user_begin) < 0) { + // "f" is completely before specified range; skip it + } else if (end != nullptr && user_cmp->Compare(file_start, user_end) > 0) { + // "f" is completely after specified range; skip it + } else { + inputs->push_back(f); + if (level == 0) { + // Level-0 files may overlap each other. So check if the newly + // added file has expanded the range. If so, restart search. + if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) { + user_begin = file_start; + inputs->clear(); + i = 0; + } else if (end != nullptr && + user_cmp->Compare(file_limit, user_end) > 0) { + user_end = file_limit; + inputs->clear(); + i = 0; + } + } + } + } +} + +std::string Version::DebugString() const { + std::string r; + for (int level = 0; level < config::kNumLevels; level++) { + // E.g., + // --- level 1 --- + // 17:123['a' .. 'd'] + // 20:43['e' .. 'g'] + r.append("--- level "); + AppendNumberTo(&r, level); + r.append(" ---\n"); + const std::vector& files = files_[level]; + for (size_t i = 0; i < files.size(); i++) { + r.push_back(' '); + AppendNumberTo(&r, files[i]->number); + r.push_back(':'); + AppendNumberTo(&r, files[i]->file_size); + r.append("["); + r.append(files[i]->smallest.DebugString()); + r.append(" .. "); + r.append(files[i]->largest.DebugString()); + r.append("]\n"); + } + } + return r; +} + +// A helper class so we can efficiently apply a whole sequence +// of edits to a particular state without creating intermediate +// Versions that contain full copies of the intermediate state. +class VersionSet::Builder { + private: + // Helper to sort by v->files_[file_number].smallest + struct BySmallestKey { + const InternalKeyComparator* internal_comparator; + + bool operator()(FileMetaData* f1, FileMetaData* f2) const { + int r = internal_comparator->Compare(f1->smallest, f2->smallest); + if (r != 0) { + return (r < 0); + } else { + // Break ties by file number + return (f1->number < f2->number); + } + } + }; + + typedef std::set FileSet; + struct LevelState { + std::set deleted_files; + FileSet* added_files; + }; + + VersionSet* vset_; + Version* base_; + LevelState levels_[config::kNumLevels]; + + public: + // Initialize a builder with the files from *base and other info from *vset + Builder(VersionSet* vset, Version* base) : vset_(vset), base_(base) { + base_->Ref(); + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + levels_[level].added_files = new FileSet(cmp); + } + } + + ~Builder() { + for (int level = 0; level < config::kNumLevels; level++) { + const FileSet* added = levels_[level].added_files; + std::vector to_unref; + to_unref.reserve(added->size()); + for (FileSet::const_iterator it = added->begin(); it != added->end(); + ++it) { + to_unref.push_back(*it); + } + delete added; + for (uint32_t i = 0; i < to_unref.size(); i++) { + FileMetaData* f = to_unref[i]; + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + base_->Unref(); + } + + // Apply all of the edits in *edit to the current state. + void Apply(VersionEdit* edit) { + // Update compaction pointers + for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { + const int level = edit->compact_pointers_[i].first; + vset_->compact_pointer_[level] = + edit->compact_pointers_[i].second.Encode().ToString(); + } + + // Delete files + const VersionEdit::DeletedFileSet& del = edit->deleted_files_; + for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); + iter != del.end(); ++iter) { + const int level = iter->first; + const uint64_t number = iter->second; + levels_[level].deleted_files.insert(number); + } + + // Add new files + for (size_t i = 0; i < edit->new_files_.size(); i++) { + const int level = edit->new_files_[i].first; + FileMetaData* f = new FileMetaData(edit->new_files_[i].second); + f->refs = 1; + + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = static_cast((f->file_size / 16384U)); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + + levels_[level].deleted_files.erase(f->number); + levels_[level].added_files->insert(f); + } + } + + // Save the current state in *v. + void SaveTo(Version* v) { + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + // Merge the set of added files with the set of pre-existing files. + // Drop any deleted files. Store the result in *v. + const std::vector& base_files = base_->files_[level]; + std::vector::const_iterator base_iter = base_files.begin(); + std::vector::const_iterator base_end = base_files.end(); + const FileSet* added = levels_[level].added_files; + v->files_[level].reserve(base_files.size() + added->size()); + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); ++added_iter) { + // Add all smaller files listed in base_ + for (std::vector::const_iterator bpos = + std::upper_bound(base_iter, base_end, *added_iter, cmp); + base_iter != bpos; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + + MaybeAddFile(v, level, *added_iter); + } + + // Add remaining base files + for (; base_iter != base_end; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + +#ifndef NDEBUG + // Make sure there is no overlap in levels > 0 + if (level > 0) { + for (uint32_t i = 1; i < v->files_[level].size(); i++) { + const InternalKey& prev_end = v->files_[level][i - 1]->largest; + const InternalKey& this_begin = v->files_[level][i]->smallest; + if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { + fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", + prev_end.DebugString().c_str(), + this_begin.DebugString().c_str()); + abort(); + } + } + } +#endif + } + } + + void MaybeAddFile(Version* v, int level, FileMetaData* f) { + if (levels_[level].deleted_files.count(f->number) > 0) { + // File is deleted: do nothing + } else { + std::vector* files = &v->files_[level]; + if (level > 0 && !files->empty()) { + // Must not overlap + assert(vset_->icmp_.Compare((*files)[files->size() - 1]->largest, + f->smallest) < 0); + } + f->refs++; + files->push_back(f); + } + } +}; + +VersionSet::VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, + const InternalKeyComparator* cmp) + : env_(options->env), + dbname_(dbname), + options_(options), + table_cache_(table_cache), + icmp_(*cmp), + next_file_number_(2), + manifest_file_number_(0), // Filled by Recover() + last_sequence_(0), + log_number_(0), + prev_log_number_(0), + descriptor_file_(nullptr), + descriptor_log_(nullptr), + dummy_versions_(this), + current_(nullptr) { + AppendVersion(new Version(this)); +} + +VersionSet::~VersionSet() { + current_->Unref(); + assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty + delete descriptor_log_; + delete descriptor_file_; +} + +void VersionSet::AppendVersion(Version* v) { + // Make "v" current + assert(v->refs_ == 0); + assert(v != current_); + if (current_ != nullptr) { + current_->Unref(); + } + current_ = v; + v->Ref(); + + // Append to linked list + v->prev_ = dummy_versions_.prev_; + v->next_ = &dummy_versions_; + v->prev_->next_ = v; + v->next_->prev_ = v; +} + +Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) { + if (edit->has_log_number_) { + assert(edit->log_number_ >= log_number_); + assert(edit->log_number_ < next_file_number_); + } else { + edit->SetLogNumber(log_number_); + } + + if (!edit->has_prev_log_number_) { + edit->SetPrevLogNumber(prev_log_number_); + } + + edit->SetNextFile(next_file_number_); + edit->SetLastSequence(last_sequence_); + + Version* v = new Version(this); + { + Builder builder(this, current_); + builder.Apply(edit); + builder.SaveTo(v); + } + Finalize(v); + + // Initialize new descriptor log file if necessary by creating + // a temporary file that contains a snapshot of the current version. + std::string new_manifest_file; + Status s; + if (descriptor_log_ == nullptr) { + // No reason to unlock *mu here since we only hit this path in the + // first call to LogAndApply (when opening the database). + assert(descriptor_file_ == nullptr); + new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); + edit->SetNextFile(next_file_number_); + s = env_->NewWritableFile(new_manifest_file, &descriptor_file_); + if (s.ok()) { + descriptor_log_ = new log::Writer(descriptor_file_); + s = WriteSnapshot(descriptor_log_); + } + } + + // Unlock during expensive MANIFEST log write + { + mu->Unlock(); + + // Write new record to MANIFEST log + if (s.ok()) { + std::string record; + edit->EncodeTo(&record); + s = descriptor_log_->AddRecord(record); + if (s.ok()) { + s = descriptor_file_->Sync(); + } + if (!s.ok()) { + Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); + } + } + + // If we just created a new descriptor file, install it by writing a + // new CURRENT file that points to it. + if (s.ok() && !new_manifest_file.empty()) { + s = SetCurrentFile(env_, dbname_, manifest_file_number_); + } + + mu->Lock(); + } + + // Install the new version + if (s.ok()) { + AppendVersion(v); + log_number_ = edit->log_number_; + prev_log_number_ = edit->prev_log_number_; + } else { + delete v; + if (!new_manifest_file.empty()) { + delete descriptor_log_; + delete descriptor_file_; + descriptor_log_ = nullptr; + descriptor_file_ = nullptr; + env_->DeleteFile(new_manifest_file); + } + } + + return s; +} + +Status VersionSet::Recover(bool* save_manifest) { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Read "CURRENT" file, which contains a pointer to the current manifest file + std::string current; + Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); + if (!s.ok()) { + return s; + } + if (current.empty() || current[current.size() - 1] != '\n') { + return Status::Corruption("CURRENT file does not end with newline"); + } + current.resize(current.size() - 1); + + std::string dscname = dbname_ + "/" + current; + SequentialFile* file; + s = env_->NewSequentialFile(dscname, &file); + if (!s.ok()) { + if (s.IsNotFound()) { + return Status::Corruption("CURRENT points to a non-existent file", + s.ToString()); + } + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(file, &reporter, true /*checksum*/, + 0 /*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit; + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + " does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + delete file; + file = nullptr; + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + + // See if we can reuse the existing MANIFEST file. + if (ReuseManifest(dscname, current)) { + // No need to save new manifest + } else { + *save_manifest = true; + } + } + + return s; +} + +bool VersionSet::ReuseManifest(const std::string& dscname, + const std::string& dscbase) { + if (!options_->reuse_logs) { + return false; + } + FileType manifest_type; + uint64_t manifest_number; + uint64_t manifest_size; + if (!ParseFileName(dscbase, &manifest_number, &manifest_type) || + manifest_type != kDescriptorFile || + !env_->GetFileSize(dscname, &manifest_size).ok() || + // Make new compacted MANIFEST if old one is too big + manifest_size >= TargetFileSize(options_)) { + return false; + } + + assert(descriptor_file_ == nullptr); + assert(descriptor_log_ == nullptr); + Status r = env_->NewAppendableFile(dscname, &descriptor_file_); + if (!r.ok()) { + Log(options_->info_log, "Reuse MANIFEST: %s\n", r.ToString().c_str()); + assert(descriptor_file_ == nullptr); + return false; + } + + Log(options_->info_log, "Reusing MANIFEST %s\n", dscname.c_str()); + descriptor_log_ = new log::Writer(descriptor_file_, manifest_size); + manifest_file_number_ = manifest_number; + return true; +} + +void VersionSet::MarkFileNumberUsed(uint64_t number) { + if (next_file_number_ <= number) { + next_file_number_ = number + 1; + } +} + +void VersionSet::Finalize(Version* v) { + // Precomputed best level for next compaction + int best_level = -1; + double best_score = -1; + + for (int level = 0; level < config::kNumLevels - 1; level++) { + double score; + if (level == 0) { + // We treat level-0 specially by bounding the number of files + // instead of number of bytes for two reasons: + // + // (1) With larger write-buffer sizes, it is nice not to do too + // many level-0 compactions. + // + // (2) The files in level-0 are merged on every read and + // therefore we wish to avoid too many files when the individual + // file size is small (perhaps because of a small write-buffer + // setting, or very high compression ratios, or lots of + // overwrites/deletions). + score = v->files_[level].size() / + static_cast(config::kL0_CompactionTrigger); + } else { + // Compute the ratio of current size to size limit. + const uint64_t level_bytes = TotalFileSize(v->files_[level]); + score = + static_cast(level_bytes) / MaxBytesForLevel(options_, level); + } + + if (score > best_score) { + best_level = level; + best_score = score; + } + } + + v->compaction_level_ = best_level; + v->compaction_score_ = best_score; +} + +Status VersionSet::WriteSnapshot(log::Writer* log) { + // TODO: Break up into multiple records to reduce memory usage on recovery? + + // Save metadata + VersionEdit edit; + edit.SetComparatorName(icmp_.user_comparator()->Name()); + + // Save compaction pointers + for (int level = 0; level < config::kNumLevels; level++) { + if (!compact_pointer_[level].empty()) { + InternalKey key; + key.DecodeFrom(compact_pointer_[level]); + edit.SetCompactPointer(level, key); + } + } + + // Save files + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = current_->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); + } + } + + std::string record; + edit.EncodeTo(&record); + return log->AddRecord(record); +} + +int VersionSet::NumLevelFiles(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return current_->files_[level].size(); +} + +const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { + // Update code if kNumLevels changes + static_assert(config::kNumLevels == 7, ""); + snprintf(scratch->buffer, sizeof(scratch->buffer), + "files[ %d %d %d %d %d %d %d ]", int(current_->files_[0].size()), + int(current_->files_[1].size()), int(current_->files_[2].size()), + int(current_->files_[3].size()), int(current_->files_[4].size()), + int(current_->files_[5].size()), int(current_->files_[6].size())); + return scratch->buffer; +} + +uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { + uint64_t result = 0; + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + if (icmp_.Compare(files[i]->largest, ikey) <= 0) { + // Entire file is before "ikey", so just add the file size + result += files[i]->file_size; + } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { + // Entire file is after "ikey", so ignore + if (level > 0) { + // Files other than level 0 are sorted by meta->smallest, so + // no further files in this level will contain data for + // "ikey". + break; + } + } else { + // "ikey" falls in the range for this table. Add the + // approximate offset of "ikey" within the table. + Table* tableptr; + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); + if (tableptr != nullptr) { + result += tableptr->ApproximateOffsetOf(ikey.Encode()); + } + delete iter; + } + } + } + return result; +} + +void VersionSet::AddLiveFiles(std::set* live) { + for (Version* v = dummy_versions_.next_; v != &dummy_versions_; + v = v->next_) { + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } + } +} + +int64_t VersionSet::NumLevelBytes(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return TotalFileSize(current_->files_[level]); +} + +int64_t VersionSet::MaxNextLevelOverlappingBytes() { + int64_t result = 0; + std::vector overlaps; + for (int level = 1; level < config::kNumLevels - 1; level++) { + for (size_t i = 0; i < current_->files_[level].size(); i++) { + const FileMetaData* f = current_->files_[level][i]; + current_->GetOverlappingInputs(level + 1, &f->smallest, &f->largest, + &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > result) { + result = sum; + } + } + } + return result; +} + +// Stores the minimal range that covers all entries in inputs in +// *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange(const std::vector& inputs, + InternalKey* smallest, InternalKey* largest) { + assert(!inputs.empty()); + smallest->Clear(); + largest->Clear(); + for (size_t i = 0; i < inputs.size(); i++) { + FileMetaData* f = inputs[i]; + if (i == 0) { + *smallest = f->smallest; + *largest = f->largest; + } else { + if (icmp_.Compare(f->smallest, *smallest) < 0) { + *smallest = f->smallest; + } + if (icmp_.Compare(f->largest, *largest) > 0) { + *largest = f->largest; + } + } + } +} + +// Stores the minimal range that covers all entries in inputs1 and inputs2 +// in *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest) { + std::vector all = inputs1; + all.insert(all.end(), inputs2.begin(), inputs2.end()); + GetRange(all, smallest, largest); +} + +Iterator* VersionSet::MakeInputIterator(Compaction* c) { + ReadOptions options; + options.verify_checksums = options_->paranoid_checks; + options.fill_cache = false; + + // Level-0 files have to be merged together. For other levels, + // we will make a concatenating iterator per level. + // TODO(opt): use concatenating iterator for level-0 if there is no overlap + const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); + Iterator** list = new Iterator*[space]; + int num = 0; + for (int which = 0; which < 2; which++) { + if (!c->inputs_[which].empty()) { + if (c->level() + which == 0) { + const std::vector& files = c->inputs_[which]; + for (size_t i = 0; i < files.size(); i++) { + list[num++] = table_cache_->NewIterator(options, files[i]->number, + files[i]->file_size); + } + } else { + // Create concatenating iterator for the files from this level + list[num++] = NewTwoLevelIterator( + new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), + &GetFileIterator, table_cache_, options); + } + } + } + assert(num <= space); + Iterator* result = NewMergingIterator(&icmp_, list, num); + delete[] list; + return result; +} + +Compaction* VersionSet::PickCompaction() { + Compaction* c; + int level; + + // We prefer compactions triggered by too much data in a level over + // the compactions triggered by seeks. + const bool size_compaction = (current_->compaction_score_ >= 1); + const bool seek_compaction = (current_->file_to_compact_ != nullptr); + if (size_compaction) { + level = current_->compaction_level_; + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + c = new Compaction(options_, level); + + // Pick the first file that comes after compact_pointer_[level] + for (size_t i = 0; i < current_->files_[level].size(); i++) { + FileMetaData* f = current_->files_[level][i]; + if (compact_pointer_[level].empty() || + icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) { + c->inputs_[0].push_back(f); + break; + } + } + if (c->inputs_[0].empty()) { + // Wrap-around to the beginning of the key space + c->inputs_[0].push_back(current_->files_[level][0]); + } + } else if (seek_compaction) { + level = current_->file_to_compact_level_; + c = new Compaction(options_, level); + c->inputs_[0].push_back(current_->file_to_compact_); + } else { + return nullptr; + } + + c->input_version_ = current_; + c->input_version_->Ref(); + + // Files in level 0 may overlap each other, so pick up all overlapping ones + if (level == 0) { + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + // Note that the next call will discard the file we placed in + // c->inputs_[0] earlier and replace it with an overlapping set + // which will include the picked file. + current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); + assert(!c->inputs_[0].empty()); + } + + SetupOtherInputs(c); + + return c; +} + +// Finds the largest key in a vector of files. Returns true if files it not +// empty. +bool FindLargestKey(const InternalKeyComparator& icmp, + const std::vector& files, + InternalKey* largest_key) { + if (files.empty()) { + return false; + } + *largest_key = files[0]->largest; + for (size_t i = 1; i < files.size(); ++i) { + FileMetaData* f = files[i]; + if (icmp.Compare(f->largest, *largest_key) > 0) { + *largest_key = f->largest; + } + } + return true; +} + +// Finds minimum file b2=(l2, u2) in level file for which l2 > u1 and +// user_key(l2) = user_key(u1) +FileMetaData* FindSmallestBoundaryFile( + const InternalKeyComparator& icmp, + const std::vector& level_files, + const InternalKey& largest_key) { + const Comparator* user_cmp = icmp.user_comparator(); + FileMetaData* smallest_boundary_file = nullptr; + for (size_t i = 0; i < level_files.size(); ++i) { + FileMetaData* f = level_files[i]; + if (icmp.Compare(f->smallest, largest_key) > 0 && + user_cmp->Compare(f->smallest.user_key(), largest_key.user_key()) == + 0) { + if (smallest_boundary_file == nullptr || + icmp.Compare(f->smallest, smallest_boundary_file->smallest) < 0) { + smallest_boundary_file = f; + } + } + } + return smallest_boundary_file; +} + +// Extracts the largest file b1 from |compaction_files| and then searches for a +// b2 in |level_files| for which user_key(u1) = user_key(l2). If it finds such a +// file b2 (known as a boundary file) it adds it to |compaction_files| and then +// searches again using this new upper bound. +// +// If there are two blocks, b1=(l1, u1) and b2=(l2, u2) and +// user_key(u1) = user_key(l2), and if we compact b1 but not b2 then a +// subsequent get operation will yield an incorrect result because it will +// return the record from b2 in level i rather than from b1 because it searches +// level by level for records matching the supplied user key. +// +// parameters: +// in level_files: List of files to search for boundary files. +// in/out compaction_files: List of files to extend by adding boundary files. +void AddBoundaryInputs(const InternalKeyComparator& icmp, + const std::vector& level_files, + std::vector* compaction_files) { + InternalKey largest_key; + + // Quick return if compaction_files is empty. + if (!FindLargestKey(icmp, *compaction_files, &largest_key)) { + return; + } + + bool continue_searching = true; + while (continue_searching) { + FileMetaData* smallest_boundary_file = + FindSmallestBoundaryFile(icmp, level_files, largest_key); + + // If a boundary file was found advance largest_key, otherwise we're done. + if (smallest_boundary_file != NULL) { + compaction_files->push_back(smallest_boundary_file); + largest_key = smallest_boundary_file->largest; + } else { + continue_searching = false; + } + } +} + +void VersionSet::SetupOtherInputs(Compaction* c) { + const int level = c->level(); + InternalKey smallest, largest; + + AddBoundaryInputs(icmp_, current_->files_[level], &c->inputs_[0]); + GetRange(c->inputs_[0], &smallest, &largest); + + current_->GetOverlappingInputs(level + 1, &smallest, &largest, + &c->inputs_[1]); + + // Get entire range covered by compaction + InternalKey all_start, all_limit; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if (!c->inputs_[1].empty()) { + std::vector expanded0; + current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0); + AddBoundaryInputs(icmp_, current_->files_[level], &expanded0); + const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); + const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); + const int64_t expanded0_size = TotalFileSize(expanded0); + if (expanded0.size() > c->inputs_[0].size() && + inputs1_size + expanded0_size < + ExpandedCompactionByteSizeLimit(options_)) { + InternalKey new_start, new_limit; + GetRange(expanded0, &new_start, &new_limit); + std::vector expanded1; + current_->GetOverlappingInputs(level + 1, &new_start, &new_limit, + &expanded1); + if (expanded1.size() == c->inputs_[1].size()) { + Log(options_->info_log, + "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", + level, int(c->inputs_[0].size()), int(c->inputs_[1].size()), + long(inputs0_size), long(inputs1_size), int(expanded0.size()), + int(expanded1.size()), long(expanded0_size), long(inputs1_size)); + smallest = new_start; + largest = new_limit; + c->inputs_[0] = expanded0; + c->inputs_[1] = expanded1; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if (level + 2 < config::kNumLevels) { + current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, + &c->grandparents_); + } + + // Update the place where we will do the next compaction for this level. + // We update this immediately instead of waiting for the VersionEdit + // to be applied so that if the compaction fails, we will try a different + // key range next time. + compact_pointer_[level] = largest.Encode().ToString(); + c->edit_.SetCompactPointer(level, largest); +} + +Compaction* VersionSet::CompactRange(int level, const InternalKey* begin, + const InternalKey* end) { + std::vector inputs; + current_->GetOverlappingInputs(level, begin, end, &inputs); + if (inputs.empty()) { + return nullptr; + } + + // Avoid compacting too much in one shot in case the range is large. + // But we cannot do this for level-0 since level-0 files can overlap + // and we must not pick one file and drop another older file if the + // two files overlap. + if (level > 0) { + const uint64_t limit = MaxFileSizeForLevel(options_, level); + uint64_t total = 0; + for (size_t i = 0; i < inputs.size(); i++) { + uint64_t s = inputs[i]->file_size; + total += s; + if (total >= limit) { + inputs.resize(i + 1); + break; + } + } + } + + Compaction* c = new Compaction(options_, level); + c->input_version_ = current_; + c->input_version_->Ref(); + c->inputs_[0] = inputs; + SetupOtherInputs(c); + return c; +} + +Compaction::Compaction(const Options* options, int level) + : level_(level), + max_output_file_size_(MaxFileSizeForLevel(options, level)), + input_version_(nullptr), + grandparent_index_(0), + seen_key_(false), + overlapped_bytes_(0) { + for (int i = 0; i < config::kNumLevels; i++) { + level_ptrs_[i] = 0; + } +} + +Compaction::~Compaction() { + if (input_version_ != nullptr) { + input_version_->Unref(); + } +} + +bool Compaction::IsTrivialMove() const { + const VersionSet* vset = input_version_->vset_; + // Avoid a move if there is lots of overlapping grandparent data. + // Otherwise, the move could create a parent file that will require + // a very expensive merge later on. + return (num_input_files(0) == 1 && num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= + MaxGrandParentOverlapBytes(vset->options_)); +} + +void Compaction::AddInputDeletions(VersionEdit* edit) { + for (int which = 0; which < 2; which++) { + for (size_t i = 0; i < inputs_[which].size(); i++) { + edit->DeleteFile(level_ + which, inputs_[which][i]->number); + } + } +} + +bool Compaction::IsBaseLevelForKey(const Slice& user_key) { + // Maybe use binary search to find right entry instead of linear search? + const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); + for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) { + const std::vector& files = input_version_->files_[lvl]; + for (; level_ptrs_[lvl] < files.size();) { + FileMetaData* f = files[level_ptrs_[lvl]]; + if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { + // We've advanced far enough + if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { + // Key falls in this file's range, so definitely not base level + return false; + } + break; + } + level_ptrs_[lvl]++; + } + } + return true; +} + +bool Compaction::ShouldStopBefore(const Slice& internal_key) { + const VersionSet* vset = input_version_->vset_; + // Scan to find earliest grandparent file that contains key. + const InternalKeyComparator* icmp = &vset->icmp_; + while (grandparent_index_ < grandparents_.size() && + icmp->Compare(internal_key, + grandparents_[grandparent_index_]->largest.Encode()) > + 0) { + if (seen_key_) { + overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; + } + grandparent_index_++; + } + seen_key_ = true; + + if (overlapped_bytes_ > MaxGrandParentOverlapBytes(vset->options_)) { + // Too much overlap for current output; start new output + overlapped_bytes_ = 0; + return true; + } else { + return false; + } +} + +void Compaction::ReleaseInputs() { + if (input_version_ != nullptr) { + input_version_->Unref(); + input_version_ = nullptr; + } +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/version_set.h b/MyExperiences copy/Pods/leveldb-library/db/version_set.h new file mode 100644 index 00000000..69f3d701 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/version_set.h @@ -0,0 +1,393 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// The representation of a DBImpl consists of a set of Versions. The +// newest version is called "current". Older versions may be kept +// around to provide a consistent view to live iterators. +// +// Each Version keeps track of a set of Table files per level. The +// entire set of versions is maintained in a VersionSet. +// +// Version,VersionSet are thread-compatible, but require external +// synchronization on all accesses. + +#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ +#define STORAGE_LEVELDB_DB_VERSION_SET_H_ + +#include +#include +#include + +#include "db/dbformat.h" +#include "db/version_edit.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +namespace log { +class Writer; +} + +class Compaction; +class Iterator; +class MemTable; +class TableBuilder; +class TableCache; +class Version; +class VersionSet; +class WritableFile; + +// Return the smallest index i such that files[i]->largest >= key. +// Return files.size() if there is no such file. +// REQUIRES: "files" contains a sorted list of non-overlapping files. +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key); + +// Returns true iff some file in "files" overlaps the user key range +// [*smallest,*largest]. +// smallest==nullptr represents a key smaller than all keys in the DB. +// largest==nullptr represents a key largest than all keys in the DB. +// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges +// in sorted order. +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key); + +class Version { + public: + // Lookup the value for key. If found, store it in *val and + // return OK. Else return a non-OK status. Fills *stats. + // REQUIRES: lock is not held + struct GetStats { + FileMetaData* seek_file; + int seek_file_level; + }; + + // Append to *iters a sequence of iterators that will + // yield the contents of this Version when merged together. + // REQUIRES: This version has been saved (see VersionSet::SaveTo) + void AddIterators(const ReadOptions&, std::vector* iters); + + Status Get(const ReadOptions&, const LookupKey& key, std::string* val, + GetStats* stats); + + // Adds "stats" into the current state. Returns true if a new + // compaction may need to be triggered, false otherwise. + // REQUIRES: lock is held + bool UpdateStats(const GetStats& stats); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. Returns true if a new compaction may need to be triggered. + // REQUIRES: lock is held + bool RecordReadSample(Slice key); + + // Reference count management (so Versions do not disappear out from + // under live iterators) + void Ref(); + void Unref(); + + void GetOverlappingInputs( + int level, + const InternalKey* begin, // nullptr means before all keys + const InternalKey* end, // nullptr means after all keys + std::vector* inputs); + + // Returns true iff some file in the specified level overlaps + // some part of [*smallest_user_key,*largest_user_key]. + // smallest_user_key==nullptr represents a key smaller than all the DB's keys. + // largest_user_key==nullptr represents a key largest than all the DB's keys. + bool OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key); + + // Return the level at which we should place a new memtable compaction + // result that covers the range [smallest_user_key,largest_user_key]. + int PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key); + + int NumFiles(int level) const { return files_[level].size(); } + + // Return a human readable string that describes this version's contents. + std::string DebugString() const; + + private: + friend class Compaction; + friend class VersionSet; + + class LevelFileNumIterator; + + explicit Version(VersionSet* vset) + : vset_(vset), + next_(this), + prev_(this), + refs_(0), + file_to_compact_(nullptr), + file_to_compact_level_(-1), + compaction_score_(-1), + compaction_level_(-1) {} + + Version(const Version&) = delete; + Version& operator=(const Version&) = delete; + + ~Version(); + + Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; + + // Call func(arg, level, f) for every file that overlaps user_key in + // order from newest to oldest. If an invocation of func returns + // false, makes no more calls. + // + // REQUIRES: user portion of internal_key == user_key. + void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)); + + VersionSet* vset_; // VersionSet to which this Version belongs + Version* next_; // Next version in linked list + Version* prev_; // Previous version in linked list + int refs_; // Number of live refs to this version + + // List of files per level + std::vector files_[config::kNumLevels]; + + // Next file to compact based on seek stats. + FileMetaData* file_to_compact_; + int file_to_compact_level_; + + // Level that should be compacted next and its compaction score. + // Score < 1 means compaction is not strictly needed. These fields + // are initialized by Finalize(). + double compaction_score_; + int compaction_level_; +}; + +class VersionSet { + public: + VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, const InternalKeyComparator*); + VersionSet(const VersionSet&) = delete; + VersionSet& operator=(const VersionSet&) = delete; + + ~VersionSet(); + + // Apply *edit to the current version to form a new descriptor that + // is both saved to persistent state and installed as the new + // current version. Will release *mu while actually writing to the file. + // REQUIRES: *mu is held on entry. + // REQUIRES: no other thread concurrently calls LogAndApply() + Status LogAndApply(VersionEdit* edit, port::Mutex* mu) + EXCLUSIVE_LOCKS_REQUIRED(mu); + + // Recover the last saved descriptor from persistent storage. + Status Recover(bool* save_manifest); + + // Return the current version. + Version* current() const { return current_; } + + // Return the current manifest file number + uint64_t ManifestFileNumber() const { return manifest_file_number_; } + + // Allocate and return a new file number + uint64_t NewFileNumber() { return next_file_number_++; } + + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + + // Return the number of Table files at the specified level. + int NumLevelFiles(int level) const; + + // Return the combined file size of all files at the specified level. + int64_t NumLevelBytes(int level) const; + + // Return the last sequence number. + uint64_t LastSequence() const { return last_sequence_; } + + // Set the last sequence number to s. + void SetLastSequence(uint64_t s) { + assert(s >= last_sequence_); + last_sequence_ = s; + } + + // Mark the specified file number as used. + void MarkFileNumberUsed(uint64_t number); + + // Return the current log file number. + uint64_t LogNumber() const { return log_number_; } + + // Return the log file number for the log file that is currently + // being compacted, or zero if there is no such log file. + uint64_t PrevLogNumber() const { return prev_log_number_; } + + // Pick level and inputs for a new compaction. + // Returns nullptr if there is no compaction to be done. + // Otherwise returns a pointer to a heap-allocated object that + // describes the compaction. Caller should delete the result. + Compaction* PickCompaction(); + + // Return a compaction object for compacting the range [begin,end] in + // the specified level. Returns nullptr if there is nothing in that + // level that overlaps the specified range. Caller should delete + // the result. + Compaction* CompactRange(int level, const InternalKey* begin, + const InternalKey* end); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t MaxNextLevelOverlappingBytes(); + + // Create an iterator that reads over the compaction inputs for "*c". + // The caller should delete the iterator when no longer needed. + Iterator* MakeInputIterator(Compaction* c); + + // Returns true iff some level needs a compaction. + bool NeedsCompaction() const { + Version* v = current_; + return (v->compaction_score_ >= 1) || (v->file_to_compact_ != nullptr); + } + + // Add all files listed in any live version to *live. + // May also mutate some internal state. + void AddLiveFiles(std::set* live); + + // Return the approximate offset in the database of the data for + // "key" as of version "v". + uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); + + // Return a human-readable short (single-line) summary of the number + // of files per level. Uses *scratch as backing store. + struct LevelSummaryStorage { + char buffer[100]; + }; + const char* LevelSummary(LevelSummaryStorage* scratch) const; + + private: + class Builder; + + friend class Compaction; + friend class Version; + + bool ReuseManifest(const std::string& dscname, const std::string& dscbase); + + void Finalize(Version* v); + + void GetRange(const std::vector& inputs, InternalKey* smallest, + InternalKey* largest); + + void GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest); + + void SetupOtherInputs(Compaction* c); + + // Save current contents to *log + Status WriteSnapshot(log::Writer* log); + + void AppendVersion(Version* v); + + Env* const env_; + const std::string dbname_; + const Options* const options_; + TableCache* const table_cache_; + const InternalKeyComparator icmp_; + uint64_t next_file_number_; + uint64_t manifest_file_number_; + uint64_t last_sequence_; + uint64_t log_number_; + uint64_t prev_log_number_; // 0 or backing store for memtable being compacted + + // Opened lazily + WritableFile* descriptor_file_; + log::Writer* descriptor_log_; + Version dummy_versions_; // Head of circular doubly-linked list of versions. + Version* current_; // == dummy_versions_.prev_ + + // Per-level key at which the next compaction at that level should start. + // Either an empty string, or a valid InternalKey. + std::string compact_pointer_[config::kNumLevels]; +}; + +// A Compaction encapsulates information about a compaction. +class Compaction { + public: + ~Compaction(); + + // Return the level that is being compacted. Inputs from "level" + // and "level+1" will be merged to produce a set of "level+1" files. + int level() const { return level_; } + + // Return the object that holds the edits to the descriptor done + // by this compaction. + VersionEdit* edit() { return &edit_; } + + // "which" must be either 0 or 1 + int num_input_files(int which) const { return inputs_[which].size(); } + + // Return the ith input file at "level()+which" ("which" must be 0 or 1). + FileMetaData* input(int which, int i) const { return inputs_[which][i]; } + + // Maximum size of files to build during this compaction. + uint64_t MaxOutputFileSize() const { return max_output_file_size_; } + + // Is this a trivial compaction that can be implemented by just + // moving a single input file to the next level (no merging or splitting) + bool IsTrivialMove() const; + + // Add all inputs to this compaction as delete operations to *edit. + void AddInputDeletions(VersionEdit* edit); + + // Returns true if the information we have available guarantees that + // the compaction is producing data in "level+1" for which no data exists + // in levels greater than "level+1". + bool IsBaseLevelForKey(const Slice& user_key); + + // Returns true iff we should stop building the current output + // before processing "internal_key". + bool ShouldStopBefore(const Slice& internal_key); + + // Release the input version for the compaction, once the compaction + // is successful. + void ReleaseInputs(); + + private: + friend class Version; + friend class VersionSet; + + Compaction(const Options* options, int level); + + int level_; + uint64_t max_output_file_size_; + Version* input_version_; + VersionEdit edit_; + + // Each compaction reads inputs from "level_" and "level_+1" + std::vector inputs_[2]; // The two sets of inputs + + // State used to check for number of overlapping grandparent files + // (parent == level_ + 1, grandparent == level_ + 2) + std::vector grandparents_; + size_t grandparent_index_; // Index in grandparent_starts_ + bool seen_key_; // Some output key has been seen + int64_t overlapped_bytes_; // Bytes of overlap between current output + // and grandparent files + + // State for implementing IsBaseLevelForKey + + // level_ptrs_ holds indices into input_version_->levels_: our state + // is that we are positioned at one of the file ranges for each + // higher level than the ones involved in this compaction (i.e. for + // all L >= level_ + 2). + size_t level_ptrs_[config::kNumLevels]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/db/write_batch.cc b/MyExperiences copy/Pods/leveldb-library/db/write_batch.cc new file mode 100644 index 00000000..2dec6424 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/write_batch.cc @@ -0,0 +1,150 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch::rep_ := +// sequence: fixed64 +// count: fixed32 +// data: record[count] +// record := +// kTypeValue varstring varstring | +// kTypeDeletion varstring +// varstring := +// len: varint32 +// data: uint8[len] + +#include "leveldb/write_batch.h" + +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "util/coding.h" + +namespace leveldb { + +// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. +static const size_t kHeader = 12; + +WriteBatch::WriteBatch() { Clear(); } + +WriteBatch::~WriteBatch() {} + +WriteBatch::Handler::~Handler() {} + +void WriteBatch::Clear() { + rep_.clear(); + rep_.resize(kHeader); +} + +size_t WriteBatch::ApproximateSize() const { return rep_.size(); } + +Status WriteBatch::Iterate(Handler* handler) const { + Slice input(rep_); + if (input.size() < kHeader) { + return Status::Corruption("malformed WriteBatch (too small)"); + } + + input.remove_prefix(kHeader); + Slice key, value; + int found = 0; + while (!input.empty()) { + found++; + char tag = input[0]; + input.remove_prefix(1); + switch (tag) { + case kTypeValue: + if (GetLengthPrefixedSlice(&input, &key) && + GetLengthPrefixedSlice(&input, &value)) { + handler->Put(key, value); + } else { + return Status::Corruption("bad WriteBatch Put"); + } + break; + case kTypeDeletion: + if (GetLengthPrefixedSlice(&input, &key)) { + handler->Delete(key); + } else { + return Status::Corruption("bad WriteBatch Delete"); + } + break; + default: + return Status::Corruption("unknown WriteBatch tag"); + } + } + if (found != WriteBatchInternal::Count(this)) { + return Status::Corruption("WriteBatch has wrong count"); + } else { + return Status::OK(); + } +} + +int WriteBatchInternal::Count(const WriteBatch* b) { + return DecodeFixed32(b->rep_.data() + 8); +} + +void WriteBatchInternal::SetCount(WriteBatch* b, int n) { + EncodeFixed32(&b->rep_[8], n); +} + +SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { + return SequenceNumber(DecodeFixed64(b->rep_.data())); +} + +void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { + EncodeFixed64(&b->rep_[0], seq); +} + +void WriteBatch::Put(const Slice& key, const Slice& value) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + PutLengthPrefixedSlice(&rep_, value); +} + +void WriteBatch::Delete(const Slice& key) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeDeletion)); + PutLengthPrefixedSlice(&rep_, key); +} + +void WriteBatch::Append(const WriteBatch& source) { + WriteBatchInternal::Append(this, &source); +} + +namespace { +class MemTableInserter : public WriteBatch::Handler { + public: + SequenceNumber sequence_; + MemTable* mem_; + + virtual void Put(const Slice& key, const Slice& value) { + mem_->Add(sequence_, kTypeValue, key, value); + sequence_++; + } + virtual void Delete(const Slice& key) { + mem_->Add(sequence_, kTypeDeletion, key, Slice()); + sequence_++; + } +}; +} // namespace + +Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) { + MemTableInserter inserter; + inserter.sequence_ = WriteBatchInternal::Sequence(b); + inserter.mem_ = memtable; + return b->Iterate(&inserter); +} + +void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { + assert(contents.size() >= kHeader); + b->rep_.assign(contents.data(), contents.size()); +} + +void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { + SetCount(dst, Count(dst) + Count(src)); + assert(src->rep_.size() >= kHeader); + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/db/write_batch_internal.h b/MyExperiences copy/Pods/leveldb-library/db/write_batch_internal.h new file mode 100644 index 00000000..fce86e3f --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/db/write_batch_internal.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ +#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ + +#include "db/dbformat.h" +#include "leveldb/write_batch.h" + +namespace leveldb { + +class MemTable; + +// WriteBatchInternal provides static methods for manipulating a +// WriteBatch that we don't want in the public WriteBatch interface. +class WriteBatchInternal { + public: + // Return the number of entries in the batch. + static int Count(const WriteBatch* batch); + + // Set the count for the number of entries in the batch. + static void SetCount(WriteBatch* batch, int n); + + // Return the sequence number for the start of this batch. + static SequenceNumber Sequence(const WriteBatch* batch); + + // Store the specified number as the sequence number for the start of + // this batch. + static void SetSequence(WriteBatch* batch, SequenceNumber seq); + + static Slice Contents(const WriteBatch* batch) { return Slice(batch->rep_); } + + static size_t ByteSize(const WriteBatch* batch) { return batch->rep_.size(); } + + static void SetContents(WriteBatch* batch, const Slice& contents); + + static Status InsertInto(const WriteBatch* batch, MemTable* memtable); + + static void Append(WriteBatch* dst, const WriteBatch* src); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/c.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/c.h new file mode 100644 index 00000000..8e0d592a --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/c.h @@ -0,0 +1,270 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. + + C bindings for leveldb. May be useful as a stable ABI that can be + used by programs that keep leveldb in a shared library, or for + a JNI api. + + Does not support: + . getters for the option types + . custom comparators that implement key shortening + . custom iter, db, env, cache implementations using just the C bindings + + Some conventions: + + (1) We expose just opaque struct pointers and functions to clients. + This allows us to change internal representations without having to + recompile clients. + + (2) For simplicity, there is no equivalent to the Slice type. Instead, + the caller has to pass the pointer and length as separate + arguments. + + (3) Errors are represented by a null-terminated c string. NULL + means no error. All operations that can raise an error are passed + a "char** errptr" as the last argument. One of the following must + be true on entry: + *errptr == NULL + *errptr points to a malloc()ed null-terminated error message + (On Windows, *errptr must have been malloc()-ed by this library.) + On success, a leveldb routine leaves *errptr unchanged. + On failure, leveldb frees the old value of *errptr and + set *errptr to a malloc()ed error message. + + (4) Bools have the type unsigned char (0 == false; rest == true) + + (5) All of the pointer arguments must be non-NULL. +*/ + +#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ +#define STORAGE_LEVELDB_INCLUDE_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "leveldb/export.h" + +/* Exported types */ + +typedef struct leveldb_t leveldb_t; +typedef struct leveldb_cache_t leveldb_cache_t; +typedef struct leveldb_comparator_t leveldb_comparator_t; +typedef struct leveldb_env_t leveldb_env_t; +typedef struct leveldb_filelock_t leveldb_filelock_t; +typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; +typedef struct leveldb_iterator_t leveldb_iterator_t; +typedef struct leveldb_logger_t leveldb_logger_t; +typedef struct leveldb_options_t leveldb_options_t; +typedef struct leveldb_randomfile_t leveldb_randomfile_t; +typedef struct leveldb_readoptions_t leveldb_readoptions_t; +typedef struct leveldb_seqfile_t leveldb_seqfile_t; +typedef struct leveldb_snapshot_t leveldb_snapshot_t; +typedef struct leveldb_writablefile_t leveldb_writablefile_t; +typedef struct leveldb_writebatch_t leveldb_writebatch_t; +typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; + +/* DB operations */ + +LEVELDB_EXPORT leveldb_t* leveldb_open(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_close(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_put(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr); + +LEVELDB_EXPORT void leveldb_delete(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr); + +LEVELDB_EXPORT void leveldb_write(leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr); + +/* Returns NULL if not found. A malloc()ed array otherwise. + Stores the length of the array in *vallen. */ +LEVELDB_EXPORT char* leveldb_get(leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr); + +LEVELDB_EXPORT leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options); + +LEVELDB_EXPORT const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_release_snapshot( + leveldb_t* db, const leveldb_snapshot_t* snapshot); + +/* Returns NULL if property name is unknown. + Else returns a pointer to a malloc()-ed null-terminated value. */ +LEVELDB_EXPORT char* leveldb_property_value(leveldb_t* db, + const char* propname); + +LEVELDB_EXPORT void leveldb_approximate_sizes( + leveldb_t* db, int num_ranges, const char* const* range_start_key, + const size_t* range_start_key_len, const char* const* range_limit_key, + const size_t* range_limit_key_len, uint64_t* sizes); + +LEVELDB_EXPORT void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, + const char* limit_key, + size_t limit_key_len); + +/* Management operations */ + +LEVELDB_EXPORT void leveldb_destroy_db(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_repair_db(const leveldb_options_t* options, + const char* name, char** errptr); + +/* Iterator */ + +LEVELDB_EXPORT void leveldb_iter_destroy(leveldb_iterator_t*); +LEVELDB_EXPORT unsigned char leveldb_iter_valid(const leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_first(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_last(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek(leveldb_iterator_t*, const char* k, + size_t klen); +LEVELDB_EXPORT void leveldb_iter_next(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_prev(leveldb_iterator_t*); +LEVELDB_EXPORT const char* leveldb_iter_key(const leveldb_iterator_t*, + size_t* klen); +LEVELDB_EXPORT const char* leveldb_iter_value(const leveldb_iterator_t*, + size_t* vlen); +LEVELDB_EXPORT void leveldb_iter_get_error(const leveldb_iterator_t*, + char** errptr); + +/* Write batch */ + +LEVELDB_EXPORT leveldb_writebatch_t* leveldb_writebatch_create(); +LEVELDB_EXPORT void leveldb_writebatch_destroy(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_clear(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_put(leveldb_writebatch_t*, + const char* key, size_t klen, + const char* val, size_t vlen); +LEVELDB_EXPORT void leveldb_writebatch_delete(leveldb_writebatch_t*, + const char* key, size_t klen); +LEVELDB_EXPORT void leveldb_writebatch_iterate( + const leveldb_writebatch_t*, void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)); +LEVELDB_EXPORT void leveldb_writebatch_append( + leveldb_writebatch_t* destination, const leveldb_writebatch_t* source); + +/* Options */ + +LEVELDB_EXPORT leveldb_options_t* leveldb_options_create(); +LEVELDB_EXPORT void leveldb_options_destroy(leveldb_options_t*); +LEVELDB_EXPORT void leveldb_options_set_comparator(leveldb_options_t*, + leveldb_comparator_t*); +LEVELDB_EXPORT void leveldb_options_set_filter_policy(leveldb_options_t*, + leveldb_filterpolicy_t*); +LEVELDB_EXPORT void leveldb_options_set_create_if_missing(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_error_if_exists(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_paranoid_checks(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); +LEVELDB_EXPORT void leveldb_options_set_info_log(leveldb_options_t*, + leveldb_logger_t*); +LEVELDB_EXPORT void leveldb_options_set_write_buffer_size(leveldb_options_t*, + size_t); +LEVELDB_EXPORT void leveldb_options_set_max_open_files(leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_cache(leveldb_options_t*, + leveldb_cache_t*); +LEVELDB_EXPORT void leveldb_options_set_block_size(leveldb_options_t*, size_t); +LEVELDB_EXPORT void leveldb_options_set_block_restart_interval( + leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*, + size_t); + +enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 }; +LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int); + +/* Comparator */ + +LEVELDB_EXPORT leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_comparator_destroy(leveldb_comparator_t*); + +/* Filter policy */ + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( + int bits_per_key); + +/* Read options */ + +LEVELDB_EXPORT leveldb_readoptions_t* leveldb_readoptions_create(); +LEVELDB_EXPORT void leveldb_readoptions_destroy(leveldb_readoptions_t*); +LEVELDB_EXPORT void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t*, unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_snapshot(leveldb_readoptions_t*, + const leveldb_snapshot_t*); + +/* Write options */ + +LEVELDB_EXPORT leveldb_writeoptions_t* leveldb_writeoptions_create(); +LEVELDB_EXPORT void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); +LEVELDB_EXPORT void leveldb_writeoptions_set_sync(leveldb_writeoptions_t*, + unsigned char); + +/* Cache */ + +LEVELDB_EXPORT leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); +LEVELDB_EXPORT void leveldb_cache_destroy(leveldb_cache_t* cache); + +/* Env */ + +LEVELDB_EXPORT leveldb_env_t* leveldb_create_default_env(); +LEVELDB_EXPORT void leveldb_env_destroy(leveldb_env_t*); + +/* If not NULL, the returned buffer must be released using leveldb_free(). */ +LEVELDB_EXPORT char* leveldb_env_get_test_directory(leveldb_env_t*); + +/* Utility */ + +/* Calls free(ptr). + REQUIRES: ptr was malloc()-ed and returned by one of the routines + in this file. Note that in certain cases (typically on Windows), you + may need to call this routine instead of free(ptr) to dispose of + malloc()-ed memory returned by this library. */ +LEVELDB_EXPORT void leveldb_free(void* ptr); + +/* Return the major version number for this release. */ +LEVELDB_EXPORT int leveldb_major_version(); + +/* Return the minor version number for this release. */ +LEVELDB_EXPORT int leveldb_minor_version(); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/cache.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/cache.h new file mode 100644 index 00000000..7d1a2211 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/cache.h @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Cache is an interface that maps keys to values. It has internal +// synchronization and may be safely accessed concurrently from +// multiple threads. It may automatically evict entries to make room +// for new entries. Values have a specified charge against the cache +// capacity. For example, a cache where the values are variable +// length strings, may use the length of the string as the charge for +// the string. +// +// A builtin cache implementation with a least-recently-used eviction +// policy is provided. Clients may use their own implementations if +// they want something more sophisticated (like scan-resistance, a +// custom eviction policy, variable cache sizing, etc.) + +#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ +#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Cache; + +// Create a new cache with a fixed size capacity. This implementation +// of Cache uses a least-recently-used eviction policy. +LEVELDB_EXPORT Cache* NewLRUCache(size_t capacity); + +class LEVELDB_EXPORT Cache { + public: + Cache() = default; + + Cache(const Cache&) = delete; + Cache& operator=(const Cache&) = delete; + + // Destroys all existing entries by calling the "deleter" + // function that was passed to the constructor. + virtual ~Cache(); + + // Opaque handle to an entry stored in the cache. + struct Handle {}; + + // Insert a mapping from key->value into the cache and assign it + // the specified charge against the total cache capacity. + // + // Returns a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + // + // When the inserted entry is no longer needed, the key and + // value will be passed to "deleter". + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) = 0; + + // If the cache has no mapping for "key", returns nullptr. + // + // Else return a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + virtual Handle* Lookup(const Slice& key) = 0; + + // Release a mapping returned by a previous Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void Release(Handle* handle) = 0; + + // Return the value encapsulated in a handle returned by a + // successful Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void* Value(Handle* handle) = 0; + + // If the cache contains entry for key, erase it. Note that the + // underlying entry will be kept around until all existing handles + // to it have been released. + virtual void Erase(const Slice& key) = 0; + + // Return a new numeric id. May be used by multiple clients who are + // sharing the same cache to partition the key space. Typically the + // client will allocate a new id at startup and prepend the id to + // its cache keys. + virtual uint64_t NewId() = 0; + + // Remove all cache entries that are not actively in use. Memory-constrained + // applications may wish to call this method to reduce memory usage. + // Default implementation of Prune() does nothing. Subclasses are strongly + // encouraged to override the default implementation. A future release of + // leveldb may change Prune() to a pure abstract method. + virtual void Prune() {} + + // Return an estimate of the combined charges of all elements stored in the + // cache. + virtual size_t TotalCharge() const = 0; + + private: + void LRU_Remove(Handle* e); + void LRU_Append(Handle* e); + void Unref(Handle* e); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_CACHE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/comparator.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/comparator.h new file mode 100644 index 00000000..a85b51eb --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/comparator.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +// A Comparator object provides a total order across slices that are +// used as keys in an sstable or a database. A Comparator implementation +// must be thread-safe since leveldb may invoke its methods concurrently +// from multiple threads. +class LEVELDB_EXPORT Comparator { + public: + virtual ~Comparator(); + + // Three-way comparison. Returns value: + // < 0 iff "a" < "b", + // == 0 iff "a" == "b", + // > 0 iff "a" > "b" + virtual int Compare(const Slice& a, const Slice& b) const = 0; + + // The name of the comparator. Used to check for comparator + // mismatches (i.e., a DB created with one comparator is + // accessed using a different comparator. + // + // The client of this package should switch to a new name whenever + // the comparator implementation changes in a way that will cause + // the relative ordering of any two keys to change. + // + // Names starting with "leveldb." are reserved and should not be used + // by any clients of this package. + virtual const char* Name() const = 0; + + // Advanced functions: these are used to reduce the space requirements + // for internal data structures like index blocks. + + // If *start < limit, changes *start to a short string in [start,limit). + // Simple comparator implementations may return with *start unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const = 0; + + // Changes *key to a short string >= *key. + // Simple comparator implementations may return with *key unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortSuccessor(std::string* key) const = 0; +}; + +// Return a builtin comparator that uses lexicographic byte-wise +// ordering. The result remains the property of this module and +// must not be deleted. +LEVELDB_EXPORT const Comparator* BytewiseComparator(); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/db.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/db.h new file mode 100644 index 00000000..ea3d9e5a --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/db.h @@ -0,0 +1,167 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ +#define STORAGE_LEVELDB_INCLUDE_DB_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" + +namespace leveldb { + +// Update CMakeLists.txt if you change these +static const int kMajorVersion = 1; +static const int kMinorVersion = 22; + +struct Options; +struct ReadOptions; +struct WriteOptions; +class WriteBatch; + +// Abstract handle to particular state of a DB. +// A Snapshot is an immutable object and can therefore be safely +// accessed from multiple threads without any external synchronization. +class LEVELDB_EXPORT Snapshot { + protected: + virtual ~Snapshot(); +}; + +// A range of keys +struct LEVELDB_EXPORT Range { + Range() {} + Range(const Slice& s, const Slice& l) : start(s), limit(l) {} + + Slice start; // Included in the range + Slice limit; // Not included in the range +}; + +// A DB is a persistent ordered map from keys to values. +// A DB is safe for concurrent access from multiple threads without +// any external synchronization. +class LEVELDB_EXPORT DB { + public: + // Open the database with the specified "name". + // Stores a pointer to a heap-allocated database in *dbptr and returns + // OK on success. + // Stores nullptr in *dbptr and returns a non-OK status on error. + // Caller should delete *dbptr when it is no longer needed. + static Status Open(const Options& options, const std::string& name, + DB** dbptr); + + DB() = default; + + DB(const DB&) = delete; + DB& operator=(const DB&) = delete; + + virtual ~DB(); + + // Set the database entry for "key" to "value". Returns OK on success, + // and a non-OK status on error. + // Note: consider setting options.sync = true. + virtual Status Put(const WriteOptions& options, const Slice& key, + const Slice& value) = 0; + + // Remove the database entry (if any) for "key". Returns OK on + // success, and a non-OK status on error. It is not an error if "key" + // did not exist in the database. + // Note: consider setting options.sync = true. + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + + // Apply the specified updates to the database. + // Returns OK on success, non-OK on failure. + // Note: consider setting options.sync = true. + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + + // If the database contains an entry for "key" store the + // corresponding value in *value and return OK. + // + // If there is no entry for "key" leave *value unchanged and return + // a status for which Status::IsNotFound() returns true. + // + // May return some other Status on an error. + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value) = 0; + + // Return a heap-allocated iterator over the contents of the database. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + // + // Caller should delete the iterator when it is no longer needed. + // The returned iterator should be deleted before this db is deleted. + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + + // Return a handle to the current DB state. Iterators created with + // this handle will all observe a stable snapshot of the current DB + // state. The caller must call ReleaseSnapshot(result) when the + // snapshot is no longer needed. + virtual const Snapshot* GetSnapshot() = 0; + + // Release a previously acquired snapshot. The caller must not + // use "snapshot" after this call. + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + + // DB implementations can export properties about their state + // via this method. If "property" is a valid property understood by this + // DB implementation, fills "*value" with its current value and returns + // true. Otherwise returns false. + // + // + // Valid property names include: + // + // "leveldb.num-files-at-level" - return the number of files at level , + // where is an ASCII representation of a level number (e.g. "0"). + // "leveldb.stats" - returns a multi-line string that describes statistics + // about the internal operation of the DB. + // "leveldb.sstables" - returns a multi-line string that describes all + // of the sstables that make up the db contents. + // "leveldb.approximate-memory-usage" - returns the approximate number of + // bytes of memory in use by the DB. + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + + // For each i in [0,n-1], store in "sizes[i]", the approximate + // file system space used by keys in "[range[i].start .. range[i].limit)". + // + // Note that the returned sizes measure file system space usage, so + // if the user data compresses by a factor of ten, the returned + // sizes will be one-tenth the size of the corresponding user data size. + // + // The results may not include the sizes of recently written data. + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + + // Compact the underlying storage for the key range [*begin,*end]. + // In particular, deleted and overwritten versions are discarded, + // and the data is rearranged to reduce the cost of operations + // needed to access the data. This operation should typically only + // be invoked by users who understand the underlying implementation. + // + // begin==nullptr is treated as a key before all keys in the database. + // end==nullptr is treated as a key after all keys in the database. + // Therefore the following call will compact the entire database: + // db->CompactRange(nullptr, nullptr); + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; +}; + +// Destroy the contents of the specified database. +// Be very careful using this method. +// +// Note: For backwards compatibility, if DestroyDB is unable to list the +// database files, Status::OK() will still be returned masking this failure. +LEVELDB_EXPORT Status DestroyDB(const std::string& name, + const Options& options); + +// If a DB cannot be opened, you may attempt to call this method to +// resurrect as much of the contents of the database as possible. +// Some data may be lost, so be careful when calling this function +// on a database that contains important information. +LEVELDB_EXPORT Status RepairDB(const std::string& dbname, + const Options& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/dumpfile.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/dumpfile.h new file mode 100644 index 00000000..a58bc6b3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/dumpfile.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ +#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ + +#include + +#include "leveldb/env.h" +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +// Dump the contents of the file named by fname in text format to +// *dst. Makes a sequence of dst->Append() calls; each call is passed +// the newline-terminated text corresponding to a single item found +// in the file. +// +// Returns a non-OK result if fname does not name a leveldb storage +// file, or if the file cannot be read. +LEVELDB_EXPORT Status DumpFile(Env* env, const std::string& fname, + WritableFile* dst); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/env.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/env.h new file mode 100644 index 00000000..112fe964 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/env.h @@ -0,0 +1,387 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An Env is an interface used by the leveldb implementation to access +// operating system functionality like the filesystem etc. Callers +// may wish to provide a custom Env object when opening a database to +// get fine gain control; e.g., to rate limit file system operations. +// +// All Env implementations are safe for concurrent access from +// multiple threads without any external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ +#define STORAGE_LEVELDB_INCLUDE_ENV_H_ + +#include +#include + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +#if defined(_WIN32) +// The leveldb::Env class below contains a DeleteFile method. +// At the same time, , a fairly popular header +// file for Windows applications, defines a DeleteFile macro. +// +// Without any intervention on our part, the result of this +// unfortunate coincidence is that the name of the +// leveldb::Env::DeleteFile method seen by the compiler depends on +// whether was included before or after the LevelDB +// headers. +// +// To avoid headaches, we undefined DeleteFile (if defined) and +// redefine it at the bottom of this file. This way +// can be included before this file (or not at all) and the +// exported method will always be leveldb::Env::DeleteFile. +#if defined(DeleteFile) +#undef DeleteFile +#define LEVELDB_DELETEFILE_UNDEFINED +#endif // defined(DeleteFile) +#endif // defined(_WIN32) + +namespace leveldb { + +class FileLock; +class Logger; +class RandomAccessFile; +class SequentialFile; +class Slice; +class WritableFile; + +class LEVELDB_EXPORT Env { + public: + Env() = default; + + Env(const Env&) = delete; + Env& operator=(const Env&) = delete; + + virtual ~Env(); + + // Return a default environment suitable for the current operating + // system. Sophisticated users may wish to provide their own Env + // implementation instead of relying on this default environment. + // + // The result of Default() belongs to leveldb and must never be deleted. + static Env* Default(); + + // Create an object that sequentially reads the file with the specified name. + // On success, stores a pointer to the new file in *result and returns OK. + // On failure stores nullptr in *result and returns non-OK. If the file does + // not exist, returns a non-OK status. Implementations should return a + // NotFound status when the file does not exist. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) = 0; + + // Create an object supporting random-access reads from the file with the + // specified name. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. If the file does not exist, returns a non-OK + // status. Implementations should return a NotFound status when the file does + // not exist. + // + // The returned file may be concurrently accessed by multiple threads. + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) = 0; + + // Create an object that writes to a new file with the specified + // name. Deletes any existing file with the same name and creates a + // new file. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) = 0; + + // Create an object that either appends to an existing file, or + // writes to a new file (if the file does not exist to begin with). + // On success, stores a pointer to the new file in *result and + // returns OK. On failure stores nullptr in *result and returns + // non-OK. + // + // The returned file will only be accessed by one thread at a time. + // + // May return an IsNotSupportedError error if this Env does + // not allow appending to an existing file. Users of Env (including + // the leveldb implementation) must be prepared to deal with + // an Env that does not support appending. + virtual Status NewAppendableFile(const std::string& fname, + WritableFile** result); + + // Returns true iff the named file exists. + virtual bool FileExists(const std::string& fname) = 0; + + // Store in *result the names of the children of the specified directory. + // The names are relative to "dir". + // Original contents of *results are dropped. + virtual Status GetChildren(const std::string& dir, + std::vector* result) = 0; + + // Delete the named file. + virtual Status DeleteFile(const std::string& fname) = 0; + + // Create the specified directory. + virtual Status CreateDir(const std::string& dirname) = 0; + + // Delete the specified directory. + virtual Status DeleteDir(const std::string& dirname) = 0; + + // Store the size of fname in *file_size. + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; + + // Rename file src to target. + virtual Status RenameFile(const std::string& src, + const std::string& target) = 0; + + // Lock the specified file. Used to prevent concurrent access to + // the same db by multiple processes. On failure, stores nullptr in + // *lock and returns non-OK. + // + // On success, stores a pointer to the object that represents the + // acquired lock in *lock and returns OK. The caller should call + // UnlockFile(*lock) to release the lock. If the process exits, + // the lock will be automatically released. + // + // If somebody else already holds the lock, finishes immediately + // with a failure. I.e., this call does not wait for existing locks + // to go away. + // + // May create the named file if it does not already exist. + virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; + + // Release the lock acquired by a previous successful call to LockFile. + // REQUIRES: lock was returned by a successful LockFile() call + // REQUIRES: lock has not already been unlocked. + virtual Status UnlockFile(FileLock* lock) = 0; + + // Arrange to run "(*function)(arg)" once in a background thread. + // + // "function" may run in an unspecified thread. Multiple functions + // added to the same Env may run concurrently in different threads. + // I.e., the caller may not assume that background work items are + // serialized. + virtual void Schedule(void (*function)(void* arg), void* arg) = 0; + + // Start a new thread, invoking "function(arg)" within the new thread. + // When "function(arg)" returns, the thread will be destroyed. + virtual void StartThread(void (*function)(void* arg), void* arg) = 0; + + // *path is set to a temporary directory that can be used for testing. It may + // or may not have just been created. The directory may or may not differ + // between runs of the same process, but subsequent calls will return the + // same directory. + virtual Status GetTestDirectory(std::string* path) = 0; + + // Create and return a log file for storing informational messages. + virtual Status NewLogger(const std::string& fname, Logger** result) = 0; + + // Returns the number of micro-seconds since some fixed point in time. Only + // useful for computing deltas of time. + virtual uint64_t NowMicros() = 0; + + // Sleep/delay the thread for the prescribed number of micro-seconds. + virtual void SleepForMicroseconds(int micros) = 0; +}; + +// A file abstraction for reading sequentially through a file +class LEVELDB_EXPORT SequentialFile { + public: + SequentialFile() = default; + + SequentialFile(const SequentialFile&) = delete; + SequentialFile& operator=(const SequentialFile&) = delete; + + virtual ~SequentialFile(); + + // Read up to "n" bytes from the file. "scratch[0..n-1]" may be + // written by this routine. Sets "*result" to the data that was + // read (including if fewer than "n" bytes were successfully read). + // May set "*result" to point at data in "scratch[0..n-1]", so + // "scratch[0..n-1]" must be live when "*result" is used. + // If an error was encountered, returns a non-OK status. + // + // REQUIRES: External synchronization + virtual Status Read(size_t n, Slice* result, char* scratch) = 0; + + // Skip "n" bytes from the file. This is guaranteed to be no + // slower that reading the same data, but may be faster. + // + // If end of file is reached, skipping will stop at the end of the + // file, and Skip will return OK. + // + // REQUIRES: External synchronization + virtual Status Skip(uint64_t n) = 0; +}; + +// A file abstraction for randomly reading the contents of a file. +class LEVELDB_EXPORT RandomAccessFile { + public: + RandomAccessFile() = default; + + RandomAccessFile(const RandomAccessFile&) = delete; + RandomAccessFile& operator=(const RandomAccessFile&) = delete; + + virtual ~RandomAccessFile(); + + // Read up to "n" bytes from the file starting at "offset". + // "scratch[0..n-1]" may be written by this routine. Sets "*result" + // to the data that was read (including if fewer than "n" bytes were + // successfully read). May set "*result" to point at data in + // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when + // "*result" is used. If an error was encountered, returns a non-OK + // status. + // + // Safe for concurrent use by multiple threads. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const = 0; +}; + +// A file abstraction for sequential writing. The implementation +// must provide buffering since callers may append small fragments +// at a time to the file. +class LEVELDB_EXPORT WritableFile { + public: + WritableFile() = default; + + WritableFile(const WritableFile&) = delete; + WritableFile& operator=(const WritableFile&) = delete; + + virtual ~WritableFile(); + + virtual Status Append(const Slice& data) = 0; + virtual Status Close() = 0; + virtual Status Flush() = 0; + virtual Status Sync() = 0; +}; + +// An interface for writing log messages. +class LEVELDB_EXPORT Logger { + public: + Logger() = default; + + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; + + virtual ~Logger(); + + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap) = 0; +}; + +// Identifies a locked file. +class LEVELDB_EXPORT FileLock { + public: + FileLock() = default; + + FileLock(const FileLock&) = delete; + FileLock& operator=(const FileLock&) = delete; + + virtual ~FileLock(); +}; + +// Log the specified data to *info_log if info_log is non-null. +void Log(Logger* info_log, const char* format, ...) +#if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +// A utility routine: write "data" to the named file. +LEVELDB_EXPORT Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname); + +// A utility routine: read contents of named file into *data +LEVELDB_EXPORT Status ReadFileToString(Env* env, const std::string& fname, + std::string* data); + +// An implementation of Env that forwards all calls to another Env. +// May be useful to clients who wish to override just part of the +// functionality of another Env. +class LEVELDB_EXPORT EnvWrapper : public Env { + public: + // Initialize an EnvWrapper that delegates all calls to *t. + explicit EnvWrapper(Env* t) : target_(t) {} + virtual ~EnvWrapper(); + + // Return the target to which this Env forwards all calls. + Env* target() const { return target_; } + + // The following text is boilerplate that forwards all methods to target(). + Status NewSequentialFile(const std::string& f, SequentialFile** r) override { + return target_->NewSequentialFile(f, r); + } + Status NewRandomAccessFile(const std::string& f, + RandomAccessFile** r) override { + return target_->NewRandomAccessFile(f, r); + } + Status NewWritableFile(const std::string& f, WritableFile** r) override { + return target_->NewWritableFile(f, r); + } + Status NewAppendableFile(const std::string& f, WritableFile** r) override { + return target_->NewAppendableFile(f, r); + } + bool FileExists(const std::string& f) override { + return target_->FileExists(f); + } + Status GetChildren(const std::string& dir, + std::vector* r) override { + return target_->GetChildren(dir, r); + } + Status DeleteFile(const std::string& f) override { + return target_->DeleteFile(f); + } + Status CreateDir(const std::string& d) override { + return target_->CreateDir(d); + } + Status DeleteDir(const std::string& d) override { + return target_->DeleteDir(d); + } + Status GetFileSize(const std::string& f, uint64_t* s) override { + return target_->GetFileSize(f, s); + } + Status RenameFile(const std::string& s, const std::string& t) override { + return target_->RenameFile(s, t); + } + Status LockFile(const std::string& f, FileLock** l) override { + return target_->LockFile(f, l); + } + Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); } + void Schedule(void (*f)(void*), void* a) override { + return target_->Schedule(f, a); + } + void StartThread(void (*f)(void*), void* a) override { + return target_->StartThread(f, a); + } + Status GetTestDirectory(std::string* path) override { + return target_->GetTestDirectory(path); + } + Status NewLogger(const std::string& fname, Logger** result) override { + return target_->NewLogger(fname, result); + } + uint64_t NowMicros() override { return target_->NowMicros(); } + void SleepForMicroseconds(int micros) override { + target_->SleepForMicroseconds(micros); + } + + private: + Env* target_; +}; + +} // namespace leveldb + +// Redefine DeleteFile if necessary. +#if defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) +#if defined(UNICODE) +#define DeleteFile DeleteFileW +#else +#define DeleteFile DeleteFileA +#endif // defined(UNICODE) +#endif // defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) + +#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/export.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/export.h new file mode 100644 index 00000000..6ba9b183 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/export.h @@ -0,0 +1,33 @@ +// Copyright (c) 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_EXPORT_H_ +#define STORAGE_LEVELDB_INCLUDE_EXPORT_H_ + +#if !defined(LEVELDB_EXPORT) + +#if defined(LEVELDB_SHARED_LIBRARY) +#if defined(_WIN32) + +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __declspec(dllexport) +#else +#define LEVELDB_EXPORT __declspec(dllimport) +#endif // defined(LEVELDB_COMPILE_LIBRARY) + +#else // defined(_WIN32) +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __attribute__((visibility("default"))) +#else +#define LEVELDB_EXPORT +#endif +#endif // defined(_WIN32) + +#else // defined(LEVELDB_SHARED_LIBRARY) +#define LEVELDB_EXPORT +#endif + +#endif // !defined(LEVELDB_EXPORT) + +#endif // STORAGE_LEVELDB_INCLUDE_EXPORT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/filter_policy.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/filter_policy.h new file mode 100644 index 00000000..49c8eda7 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/filter_policy.h @@ -0,0 +1,72 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A database can be configured with a custom FilterPolicy object. +// This object is responsible for creating a small filter from a set +// of keys. These filters are stored in leveldb and are consulted +// automatically by leveldb to decide whether or not to read some +// information from disk. In many cases, a filter can cut down the +// number of disk seeks form a handful to a single disk seek per +// DB::Get() call. +// +// Most people will want to use the builtin bloom filter support (see +// NewBloomFilterPolicy() below). + +#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ +#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT FilterPolicy { + public: + virtual ~FilterPolicy(); + + // Return the name of this policy. Note that if the filter encoding + // changes in an incompatible way, the name returned by this method + // must be changed. Otherwise, old incompatible filters may be + // passed to methods of this type. + virtual const char* Name() const = 0; + + // keys[0,n-1] contains a list of keys (potentially with duplicates) + // that are ordered according to the user supplied comparator. + // Append a filter that summarizes keys[0,n-1] to *dst. + // + // Warning: do not change the initial contents of *dst. Instead, + // append the newly constructed filter to *dst. + virtual void CreateFilter(const Slice* keys, int n, + std::string* dst) const = 0; + + // "filter" contains the data appended by a preceding call to + // CreateFilter() on this class. This method must return true if + // the key was in the list of keys passed to CreateFilter(). + // This method may return true or false if the key was not on the + // list, but it should aim to return false with a high probability. + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; +}; + +// Return a new filter policy that uses a bloom filter with approximately +// the specified number of bits per key. A good value for bits_per_key +// is 10, which yields a filter with ~ 1% false positive rate. +// +// Callers must delete the result after any database that is using the +// result has been closed. +// +// Note: if you are using a custom comparator that ignores some parts +// of the keys being compared, you must not use NewBloomFilterPolicy() +// and must provide your own FilterPolicy that also ignores the +// corresponding parts of the keys. For example, if the comparator +// ignores trailing spaces, it would be incorrect to use a +// FilterPolicy (like NewBloomFilterPolicy) that does not ignore +// trailing spaces in keys. +LEVELDB_EXPORT const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/iterator.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/iterator.h new file mode 100644 index 00000000..bb9a5df8 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/iterator.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An iterator yields a sequence of key/value pairs from a source. +// The following class defines the interface. Multiple implementations +// are provided by this library. In particular, iterators are provided +// to access the contents of a Table or a DB. +// +// Multiple threads can invoke const methods on an Iterator without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Iterator must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ + +#include "leveldb/export.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class LEVELDB_EXPORT Iterator { + public: + Iterator(); + + Iterator(const Iterator&) = delete; + Iterator& operator=(const Iterator&) = delete; + + virtual ~Iterator(); + + // An iterator is either positioned at a key/value pair, or + // not valid. This method returns true iff the iterator is valid. + virtual bool Valid() const = 0; + + // Position at the first key in the source. The iterator is Valid() + // after this call iff the source is not empty. + virtual void SeekToFirst() = 0; + + // Position at the last key in the source. The iterator is + // Valid() after this call iff the source is not empty. + virtual void SeekToLast() = 0; + + // Position at the first key in the source that is at or past target. + // The iterator is Valid() after this call iff the source contains + // an entry that comes at or past target. + virtual void Seek(const Slice& target) = 0; + + // Moves to the next entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the last entry in the source. + // REQUIRES: Valid() + virtual void Next() = 0; + + // Moves to the previous entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the first entry in source. + // REQUIRES: Valid() + virtual void Prev() = 0; + + // Return the key for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice key() const = 0; + + // Return the value for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice value() const = 0; + + // If an error has occurred, return it. Else return an ok status. + virtual Status status() const = 0; + + // Clients are allowed to register function/arg1/arg2 triples that + // will be invoked when this iterator is destroyed. + // + // Note that unlike all of the preceding methods, this method is + // not abstract and therefore clients should not override it. + using CleanupFunction = void (*)(void* arg1, void* arg2); + void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); + + private: + // Cleanup functions are stored in a single-linked list. + // The list's head node is inlined in the iterator. + struct CleanupNode { + // True if the node is not used. Only head nodes might be unused. + bool IsEmpty() const { return function == nullptr; } + // Invokes the cleanup function. + void Run() { + assert(function != nullptr); + (*function)(arg1, arg2); + } + + // The head node is used if the function pointer is not null. + CleanupFunction function; + void* arg1; + void* arg2; + CleanupNode* next; + }; + CleanupNode cleanup_head_; +}; + +// Return an empty iterator (yields nothing). +LEVELDB_EXPORT Iterator* NewEmptyIterator(); + +// Return an empty iterator with the specified status. +LEVELDB_EXPORT Iterator* NewErrorIterator(const Status& status); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/options.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/options.h new file mode 100644 index 00000000..b7487726 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/options.h @@ -0,0 +1,187 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ +#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Cache; +class Comparator; +class Env; +class FilterPolicy; +class Logger; +class Snapshot; + +// DB contents are stored in a set of blocks, each of which holds a +// sequence of key,value pairs. Each block may be compressed before +// being stored in a file. The following enum describes which +// compression method (if any) is used to compress a block. +enum CompressionType { + // NOTE: do not change the values of existing entries, as these are + // part of the persistent format on disk. + kNoCompression = 0x0, + kSnappyCompression = 0x1 +}; + +// Options to control the behavior of a database (passed to DB::Open) +struct LEVELDB_EXPORT Options { + // Create an Options object with default values for all fields. + Options(); + + // ------------------- + // Parameters that affect behavior + + // Comparator used to define the order of keys in the table. + // Default: a comparator that uses lexicographic byte-wise ordering + // + // REQUIRES: The client must ensure that the comparator supplied + // here has the same name and orders keys *exactly* the same as the + // comparator provided to previous open calls on the same DB. + const Comparator* comparator; + + // If true, the database will be created if it is missing. + bool create_if_missing = false; + + // If true, an error is raised if the database already exists. + bool error_if_exists = false; + + // If true, the implementation will do aggressive checking of the + // data it is processing and will stop early if it detects any + // errors. This may have unforeseen ramifications: for example, a + // corruption of one DB entry may cause a large number of entries to + // become unreadable or for the entire DB to become unopenable. + bool paranoid_checks = false; + + // Use the specified object to interact with the environment, + // e.g. to read/write files, schedule background work, etc. + // Default: Env::Default() + Env* env; + + // Any internal progress/error information generated by the db will + // be written to info_log if it is non-null, or to a file stored + // in the same directory as the DB contents if info_log is null. + Logger* info_log = nullptr; + + // ------------------- + // Parameters that affect performance + + // Amount of data to build up in memory (backed by an unsorted log + // on disk) before converting to a sorted on-disk file. + // + // Larger values increase performance, especially during bulk loads. + // Up to two write buffers may be held in memory at the same time, + // so you may wish to adjust this parameter to control memory usage. + // Also, a larger write buffer will result in a longer recovery time + // the next time the database is opened. + size_t write_buffer_size = 4 * 1024 * 1024; + + // Number of open files that can be used by the DB. You may need to + // increase this if your database has a large working set (budget + // one open file per 2MB of working set). + int max_open_files = 1000; + + // Control over blocks (user data is stored in a set of blocks, and + // a block is the unit of reading from disk). + + // If non-null, use the specified cache for blocks. + // If null, leveldb will automatically create and use an 8MB internal cache. + Cache* block_cache = nullptr; + + // Approximate size of user data packed per block. Note that the + // block size specified here corresponds to uncompressed data. The + // actual size of the unit read from disk may be smaller if + // compression is enabled. This parameter can be changed dynamically. + size_t block_size = 4 * 1024; + + // Number of keys between restart points for delta encoding of keys. + // This parameter can be changed dynamically. Most clients should + // leave this parameter alone. + int block_restart_interval = 16; + + // Leveldb will write up to this amount of bytes to a file before + // switching to a new one. + // Most clients should leave this parameter alone. However if your + // filesystem is more efficient with larger files, you could + // consider increasing the value. The downside will be longer + // compactions and hence longer latency/performance hiccups. + // Another reason to increase this parameter might be when you are + // initially populating a large database. + size_t max_file_size = 2 * 1024 * 1024; + + // Compress blocks using the specified compression algorithm. This + // parameter can be changed dynamically. + // + // Default: kSnappyCompression, which gives lightweight but fast + // compression. + // + // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: + // ~200-500MB/s compression + // ~400-800MB/s decompression + // Note that these speeds are significantly faster than most + // persistent storage speeds, and therefore it is typically never + // worth switching to kNoCompression. Even if the input data is + // incompressible, the kSnappyCompression implementation will + // efficiently detect that and will switch to uncompressed mode. + CompressionType compression = kSnappyCompression; + + // EXPERIMENTAL: If true, append to existing MANIFEST and log files + // when a database is opened. This can significantly speed up open. + // + // Default: currently false, but may become true later. + bool reuse_logs = false; + + // If non-null, use the specified filter policy to reduce disk reads. + // Many applications will benefit from passing the result of + // NewBloomFilterPolicy() here. + const FilterPolicy* filter_policy = nullptr; +}; + +// Options that control read operations +struct LEVELDB_EXPORT ReadOptions { + ReadOptions() = default; + + // If true, all data read from underlying storage will be + // verified against corresponding checksums. + bool verify_checksums = false; + + // Should the data read for this iteration be cached in memory? + // Callers may wish to set this field to false for bulk scans. + bool fill_cache = true; + + // If "snapshot" is non-null, read as of the supplied snapshot + // (which must belong to the DB that is being read and which must + // not have been released). If "snapshot" is null, use an implicit + // snapshot of the state at the beginning of this read operation. + const Snapshot* snapshot = nullptr; +}; + +// Options that control write operations +struct LEVELDB_EXPORT WriteOptions { + WriteOptions() = default; + + // If true, the write will be flushed from the operating system + // buffer cache (by calling WritableFile::Sync()) before the write + // is considered complete. If this flag is true, writes will be + // slower. + // + // If this flag is false, and the machine crashes, some recent + // writes may be lost. Note that if it is just the process that + // crashes (i.e., the machine does not reboot), no writes will be + // lost even if sync==false. + // + // In other words, a DB write with sync==false has similar + // crash semantics as the "write()" system call. A DB write + // with sync==true has similar crash semantics to a "write()" + // system call followed by "fsync()". + bool sync = false; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/slice.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/slice.h new file mode 100644 index 00000000..2df417dc --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/slice.h @@ -0,0 +1,115 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ +#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ + +#include +#include +#include + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class LEVELDB_EXPORT Slice { + public: + // Create an empty slice. + Slice() : data_(""), size_(0) {} + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) {} + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) {} + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) {} + + // Intentionally copyable. + Slice(const Slice&) = default; + Slice& operator=(const Slice&) = default; + + // Return a pointer to the beginning of the referenced data + const char* data() const { return data_; } + + // Return the length (in bytes) of the referenced data + size_t size() const { return size_; } + + // Return true iff the length of the referenced data is zero + bool empty() const { return size_ == 0; } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { + data_ = ""; + size_ = 0; + } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString() const { return std::string(data_, size_); } + + // Three-way comparison. Returns value: + // < 0 iff "*this" < "b", + // == 0 iff "*this" == "b", + // > 0 iff "*this" > "b" + int compare(const Slice& b) const; + + // Return true iff "x" is a prefix of "*this" + bool starts_with(const Slice& x) const { + return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0)); + } + + private: + const char* data_; + size_t size_; +}; + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); } + +inline int Slice::compare(const Slice& b) const { + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + if (r == 0) { + if (size_ < b.size_) + r = -1; + else if (size_ > b.size_) + r = +1; + } + return r; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/status.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/status.h new file mode 100644 index 00000000..e3273144 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/status.h @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Status encapsulates the result of an operation. It may indicate success, +// or it may indicate an error with an associated error message. +// +// Multiple threads can invoke const methods on a Status without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Status must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Status { + public: + // Create a success status. + Status() noexcept : state_(nullptr) {} + ~Status() { delete[] state_; } + + Status(const Status& rhs); + Status& operator=(const Status& rhs); + + Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; } + Status& operator=(Status&& rhs) noexcept; + + // Return a success status. + static Status OK() { return Status(); } + + // Return error status of an appropriate type. + static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotFound, msg, msg2); + } + static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kCorruption, msg, msg2); + } + static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotSupported, msg, msg2); + } + static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kInvalidArgument, msg, msg2); + } + static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kIOError, msg, msg2); + } + + // Returns true iff the status indicates success. + bool ok() const { return (state_ == nullptr); } + + // Returns true iff the status indicates a NotFound error. + bool IsNotFound() const { return code() == kNotFound; } + + // Returns true iff the status indicates a Corruption error. + bool IsCorruption() const { return code() == kCorruption; } + + // Returns true iff the status indicates an IOError. + bool IsIOError() const { return code() == kIOError; } + + // Returns true iff the status indicates a NotSupportedError. + bool IsNotSupportedError() const { return code() == kNotSupported; } + + // Returns true iff the status indicates an InvalidArgument. + bool IsInvalidArgument() const { return code() == kInvalidArgument; } + + // Return a string representation of this status suitable for printing. + // Returns the string "OK" for success. + std::string ToString() const; + + private: + enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5 + }; + + Code code() const { + return (state_ == nullptr) ? kOk : static_cast(state_[4]); + } + + Status(Code code, const Slice& msg, const Slice& msg2); + static const char* CopyState(const char* s); + + // OK status has a null state_. Otherwise, state_ is a new[] array + // of the following form: + // state_[0..3] == length of message + // state_[4] == code + // state_[5..] == message + const char* state_; +}; + +inline Status::Status(const Status& rhs) { + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); +} +inline Status& Status::operator=(const Status& rhs) { + // The following condition catches both aliasing (when this == &rhs), + // and the common case where both rhs and *this are ok. + if (state_ != rhs.state_) { + delete[] state_; + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); + } + return *this; +} +inline Status& Status::operator=(Status&& rhs) noexcept { + std::swap(state_, rhs.state_); + return *this; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/table.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/table.h new file mode 100644 index 00000000..25c60131 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/table.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +class Block; +class BlockHandle; +class Footer; +struct Options; +class RandomAccessFile; +struct ReadOptions; +class TableCache; + +// A Table is a sorted map from strings to strings. Tables are +// immutable and persistent. A Table may be safely accessed from +// multiple threads without external synchronization. +class LEVELDB_EXPORT Table { + public: + // Attempt to open the table that is stored in bytes [0..file_size) + // of "file", and read the metadata entries necessary to allow + // retrieving data from the table. + // + // If successful, returns ok and sets "*table" to the newly opened + // table. The client should delete "*table" when no longer needed. + // If there was an error while initializing the table, sets "*table" + // to nullptr and returns a non-ok status. Does not take ownership of + // "*source", but the client must ensure that "source" remains live + // for the duration of the returned table's lifetime. + // + // *file must remain live while this Table is in use. + static Status Open(const Options& options, RandomAccessFile* file, + uint64_t file_size, Table** table); + + Table(const Table&) = delete; + Table& operator=(const Table&) = delete; + + ~Table(); + + // Returns a new iterator over the table contents. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + Iterator* NewIterator(const ReadOptions&) const; + + // Given a key, return an approximate byte offset in the file where + // the data for that key begins (or would begin if the key were + // present in the file). The returned value is in terms of file + // bytes, and so includes effects like compression of the underlying data. + // E.g., the approximate offset of the last key in the table will + // be close to the file length. + uint64_t ApproximateOffsetOf(const Slice& key) const; + + private: + friend class TableCache; + struct Rep; + + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); + + explicit Table(Rep* rep) : rep_(rep) {} + + // Calls (*handle_result)(arg, ...) with the entry found after a call + // to Seek(key). May not make such a call if filter policy says + // that key is not present. + Status InternalGet(const ReadOptions&, const Slice& key, void* arg, + void (*handle_result)(void* arg, const Slice& k, + const Slice& v)); + + void ReadMeta(const Footer& footer); + void ReadFilter(const Slice& filter_handle_value); + + Rep* const rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/table_builder.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/table_builder.h new file mode 100644 index 00000000..7d8896bb --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/table_builder.h @@ -0,0 +1,93 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// TableBuilder provides the interface used to build a Table +// (an immutable and sorted map from keys to values). +// +// Multiple threads can invoke const methods on a TableBuilder without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same TableBuilder must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/options.h" +#include "leveldb/status.h" + +namespace leveldb { + +class BlockBuilder; +class BlockHandle; +class WritableFile; + +class LEVELDB_EXPORT TableBuilder { + public: + // Create a builder that will store the contents of the table it is + // building in *file. Does not close the file. It is up to the + // caller to close the file after calling Finish(). + TableBuilder(const Options& options, WritableFile* file); + + TableBuilder(const TableBuilder&) = delete; + TableBuilder& operator=(const TableBuilder&) = delete; + + // REQUIRES: Either Finish() or Abandon() has been called. + ~TableBuilder(); + + // Change the options used by this builder. Note: only some of the + // option fields can be changed after construction. If a field is + // not allowed to change dynamically and its value in the structure + // passed to the constructor is different from its value in the + // structure passed to this method, this method will return an error + // without changing any fields. + Status ChangeOptions(const Options& options); + + // Add key,value to the table being constructed. + // REQUIRES: key is after any previously added key according to comparator. + // REQUIRES: Finish(), Abandon() have not been called + void Add(const Slice& key, const Slice& value); + + // Advanced operation: flush any buffered key/value pairs to file. + // Can be used to ensure that two adjacent entries never live in + // the same data block. Most clients should not need to use this method. + // REQUIRES: Finish(), Abandon() have not been called + void Flush(); + + // Return non-ok iff some error has been detected. + Status status() const; + + // Finish building the table. Stops using the file passed to the + // constructor after this function returns. + // REQUIRES: Finish(), Abandon() have not been called + Status Finish(); + + // Indicate that the contents of this builder should be abandoned. Stops + // using the file passed to the constructor after this function returns. + // If the caller is not going to call Finish(), it must call Abandon() + // before destroying this builder. + // REQUIRES: Finish(), Abandon() have not been called + void Abandon(); + + // Number of calls to Add() so far. + uint64_t NumEntries() const; + + // Size of the file generated so far. If invoked after a successful + // Finish() call, returns the size of the final generated file. + uint64_t FileSize() const; + + private: + bool ok() const { return status().ok(); } + void WriteBlock(BlockBuilder* block, BlockHandle* handle); + void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/include/leveldb/write_batch.h b/MyExperiences copy/Pods/leveldb-library/include/leveldb/write_batch.h new file mode 100644 index 00000000..94d4115f --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/include/leveldb/write_batch.h @@ -0,0 +1,83 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch holds a collection of updates to apply atomically to a DB. +// +// The updates are applied in the order in which they are added +// to the WriteBatch. For example, the value of "key" will be "v3" +// after the following batch is written: +// +// batch.Put("key", "v1"); +// batch.Delete("key"); +// batch.Put("key", "v2"); +// batch.Put("key", "v3"); +// +// Multiple threads can invoke const methods on a WriteBatch without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same WriteBatch must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT WriteBatch { + public: + class LEVELDB_EXPORT Handler { + public: + virtual ~Handler(); + virtual void Put(const Slice& key, const Slice& value) = 0; + virtual void Delete(const Slice& key) = 0; + }; + + WriteBatch(); + + // Intentionally copyable. + WriteBatch(const WriteBatch&) = default; + WriteBatch& operator=(const WriteBatch&) = default; + + ~WriteBatch(); + + // Store the mapping "key->value" in the database. + void Put(const Slice& key, const Slice& value); + + // If the database contains a mapping for "key", erase it. Else do nothing. + void Delete(const Slice& key); + + // Clear all updates buffered in this batch. + void Clear(); + + // The size of the database changes caused by this batch. + // + // This number is tied to implementation details, and may change across + // releases. It is intended for LevelDB usage metrics. + size_t ApproximateSize() const; + + // Copies the operations in "source" to this batch. + // + // This runs in O(source size) time. However, the constant factor is better + // than calling Iterate() over the source batch with a Handler that replicates + // the operations into this batch. + void Append(const WriteBatch& source); + + // Support for iterating over the contents of a batch. + Status Iterate(Handler* handler) const; + + private: + friend class WriteBatchInternal; + + std::string rep_; // See comment in write_batch.cc for the format of rep_ +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/port/port.h b/MyExperiences copy/Pods/leveldb-library/port/port.h new file mode 100644 index 00000000..4b247f74 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/port/port.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_H_ +#define STORAGE_LEVELDB_PORT_PORT_H_ + +#include + +// Include the appropriate platform specific file below. If you are +// porting to a new platform, see "port_example.h" for documentation +// of what the new port_.h file must provide. +#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS) +#include "port/port_stdcxx.h" +#elif defined(LEVELDB_PLATFORM_CHROMIUM) +#include "port/port_chromium.h" +#endif + +#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/port/port_example.h b/MyExperiences copy/Pods/leveldb-library/port/port_example.h new file mode 100644 index 00000000..1a8fca24 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/port/port_example.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// This file contains the specification, but not the implementations, +// of the types/operations/etc. that should be defined by a platform +// specific port_.h file. Use this file as a reference for +// how to port this package to a new platform. + +#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ +#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +// TODO(jorlow): Many of these belong more in the environment class rather than +// here. We should try moving them and see if it affects perf. + +// The following boolean constant must be true on a little-endian machine +// and false otherwise. +static const bool kLittleEndian = true /* or some other expression */; + +// ------------------ Threading ------------------- + +// A Mutex represents an exclusive lock. +class LOCKABLE Mutex { + public: + Mutex(); + ~Mutex(); + + // Lock the mutex. Waits until other lockers have exited. + // Will deadlock if the mutex is already locked by this thread. + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + + // Unlock the mutex. + // REQUIRES: This mutex was locked by this thread. + void Unlock() UNLOCK_FUNCTION(); + + // Optionally crash if this thread does not hold this mutex. + // The implementation must be fast, especially if NDEBUG is + // defined. The implementation is allowed to skip all checks. + void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + + // Atomically release *mu and block on this condition variable until + // either a call to SignalAll(), or a call to Signal() that picks + // this thread to wakeup. + // REQUIRES: this thread holds *mu + void Wait(); + + // If there are some threads waiting, wake up at least one of them. + void Signal(); + + // Wake up all waiting threads. + void SignallAll(); +}; + +// ------------------ Compression ------------------- + +// Store the snappy compression of "input[0,input_length-1]" in *output. +// Returns false if snappy is not supported by this port. +bool Snappy_Compress(const char* input, size_t input_length, + std::string* output); + +// If input[0,input_length-1] looks like a valid snappy compressed +// buffer, store the size of the uncompressed data in *result and +// return true. Else return false. +bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result); + +// Attempt to snappy uncompress input[0,input_length-1] into *output. +// Returns true if successful, false if the input is invalid lightweight +// compressed data. +// +// REQUIRES: at least the first "n" bytes of output[] must be writable +// where "n" is the result of a successful call to +// Snappy_GetUncompressedLength. +bool Snappy_Uncompress(const char* input_data, size_t input_length, + char* output); + +// ------------------ Miscellaneous ------------------- + +// If heap profiling is not supported, returns false. +// Else repeatedly calls (*func)(arg, data, n) and then returns true. +// The concatenation of all "data[0,n-1]" fragments is the heap profile. +bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); + +// Extend the CRC to include the first n bytes of buf. +// +// Returns zero if the CRC cannot be extended using acceleration, else returns +// the newly extended CRC value (which may also be zero). +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/port/port_stdcxx.h b/MyExperiences copy/Pods/leveldb-library/port/port_stdcxx.h new file mode 100644 index 00000000..e9cb0e53 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/port/port_stdcxx.h @@ -0,0 +1,153 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ +#define STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ + +// port/port_config.h availability is automatically detected via __has_include +// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the +// configuration detection. +#if defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if LEVELDB_HAS_PORT_CONFIG_H +#include "port/port_config.h" +#endif // LEVELDB_HAS_PORT_CONFIG_H + +#elif defined(__has_include) + +#if __has_include("port/port_config.h") +#include "port/port_config.h" +#endif // __has_include("port/port_config.h") + +#endif // defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if HAVE_CRC32C +#include +#endif // HAVE_CRC32C +#if HAVE_SNAPPY +#include +#endif // HAVE_SNAPPY + +#include +#include // NOLINT +#include +#include +#include // NOLINT +#include + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +static const bool kLittleEndian = !LEVELDB_IS_BIG_ENDIAN; + +class CondVar; + +// Thinly wraps std::mutex. +class LOCKABLE Mutex { + public: + Mutex() = default; + ~Mutex() = default; + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); } + void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); } + void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {} + + private: + friend class CondVar; + std::mutex mu_; +}; + +// Thinly wraps std::condition_variable. +class CondVar { + public: + explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); } + ~CondVar() = default; + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Wait() { + std::unique_lock lock(mu_->mu_, std::adopt_lock); + cv_.wait(lock); + lock.release(); + } + void Signal() { cv_.notify_one(); } + void SignalAll() { cv_.notify_all(); } + + private: + std::condition_variable cv_; + Mutex* const mu_; +}; + +inline bool Snappy_Compress(const char* input, size_t length, + std::string* output) { +#if HAVE_SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; +#endif // HAVE_SNAPPY + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#if HAVE_SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)result; + return false; +#endif // HAVE_SNAPPY +} + +inline bool Snappy_Uncompress(const char* input, size_t length, char* output) { +#if HAVE_SNAPPY + return snappy::RawUncompress(input, length, output); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; + return false; +#endif // HAVE_SNAPPY +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + // Silence compiler warnings about unused arguments. + (void)func; + (void)arg; + return false; +} + +inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) { +#if HAVE_CRC32C + return ::crc32c::Extend(crc, reinterpret_cast(buf), size); +#else + // Silence compiler warnings about unused arguments. + (void)crc; + (void)buf; + (void)size; + return 0; +#endif // HAVE_CRC32C +} + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/port/thread_annotations.h b/MyExperiences copy/Pods/leveldb-library/port/thread_annotations.h new file mode 100644 index 00000000..1547df90 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/port/thread_annotations.h @@ -0,0 +1,108 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ +#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ + +// Use Clang's thread safety analysis annotations when available. In other +// environments, the macros receive empty definitions. +// Usage documentation: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + +#if !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#if defined(__clang__) + +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#endif // !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#ifndef GUARDED_BY +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) +#endif + +#ifndef PT_GUARDED_BY +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) +#endif + +#ifndef ACQUIRED_AFTER +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) +#endif + +#ifndef ACQUIRED_BEFORE +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_LOCKS_REQUIRED +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCKS_REQUIRED +#define SHARED_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) +#endif + +#ifndef LOCKS_EXCLUDED +#define LOCKS_EXCLUDED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) +#endif + +#ifndef LOCK_RETURNED +#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) +#endif + +#ifndef LOCKABLE +#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable) +#endif + +#ifndef SCOPED_LOCKABLE +#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) +#endif + +#ifndef EXCLUSIVE_LOCK_FUNCTION +#define EXCLUSIVE_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCK_FUNCTION +#define SHARED_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_TRYLOCK_FUNCTION +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_TRYLOCK_FUNCTION +#define SHARED_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) +#endif + +#ifndef UNLOCK_FUNCTION +#define UNLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) +#endif + +#ifndef NO_THREAD_SAFETY_ANALYSIS +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) +#endif + +#ifndef ASSERT_EXCLUSIVE_LOCK +#define ASSERT_EXCLUSIVE_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) +#endif + +#ifndef ASSERT_SHARED_LOCK +#define ASSERT_SHARED_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) +#endif + +#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/block.cc b/MyExperiences copy/Pods/leveldb-library/table/block.cc new file mode 100644 index 00000000..ad0ee98a --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/block.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Decodes the blocks generated by block_builder.cc. + +#include "table/block.h" + +#include +#include + +#include "leveldb/comparator.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +inline uint32_t Block::NumRestarts() const { + assert(size_ >= sizeof(uint32_t)); + return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); +} + +Block::Block(const BlockContents& contents) + : data_(contents.data.data()), + size_(contents.data.size()), + owned_(contents.heap_allocated) { + if (size_ < sizeof(uint32_t)) { + size_ = 0; // Error marker + } else { + size_t max_restarts_allowed = (size_ - sizeof(uint32_t)) / sizeof(uint32_t); + if (NumRestarts() > max_restarts_allowed) { + // The size is too small for NumRestarts() + size_ = 0; + } else { + restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); + } + } +} + +Block::~Block() { + if (owned_) { + delete[] data_; + } +} + +// Helper routine: decode the next block entry starting at "p", +// storing the number of shared key bytes, non_shared key bytes, +// and the length of the value in "*shared", "*non_shared", and +// "*value_length", respectively. Will not dereference past "limit". +// +// If any errors are detected, returns nullptr. Otherwise, returns a +// pointer to the key delta (just past the three decoded values). +static inline const char* DecodeEntry(const char* p, const char* limit, + uint32_t* shared, uint32_t* non_shared, + uint32_t* value_length) { + if (limit - p < 3) return nullptr; + *shared = reinterpret_cast(p)[0]; + *non_shared = reinterpret_cast(p)[1]; + *value_length = reinterpret_cast(p)[2]; + if ((*shared | *non_shared | *value_length) < 128) { + // Fast path: all three values are encoded in one byte each + p += 3; + } else { + if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr; + } + + if (static_cast(limit - p) < (*non_shared + *value_length)) { + return nullptr; + } + return p; +} + +class Block::Iter : public Iterator { + private: + const Comparator* const comparator_; + const char* const data_; // underlying block contents + uint32_t const restarts_; // Offset of restart array (list of fixed32) + uint32_t const num_restarts_; // Number of uint32_t entries in restart array + + // current_ is offset in data_ of current entry. >= restarts_ if !Valid + uint32_t current_; + uint32_t restart_index_; // Index of restart block in which current_ falls + std::string key_; + Slice value_; + Status status_; + + inline int Compare(const Slice& a, const Slice& b) const { + return comparator_->Compare(a, b); + } + + // Return the offset in data_ just past the end of the current entry. + inline uint32_t NextEntryOffset() const { + return (value_.data() + value_.size()) - data_; + } + + uint32_t GetRestartPoint(uint32_t index) { + assert(index < num_restarts_); + return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); + } + + void SeekToRestartPoint(uint32_t index) { + key_.clear(); + restart_index_ = index; + // current_ will be fixed by ParseNextKey(); + + // ParseNextKey() starts at the end of value_, so set value_ accordingly + uint32_t offset = GetRestartPoint(index); + value_ = Slice(data_ + offset, 0); + } + + public: + Iter(const Comparator* comparator, const char* data, uint32_t restarts, + uint32_t num_restarts) + : comparator_(comparator), + data_(data), + restarts_(restarts), + num_restarts_(num_restarts), + current_(restarts_), + restart_index_(num_restarts_) { + assert(num_restarts_ > 0); + } + + virtual bool Valid() const { return current_ < restarts_; } + virtual Status status() const { return status_; } + virtual Slice key() const { + assert(Valid()); + return key_; + } + virtual Slice value() const { + assert(Valid()); + return value_; + } + + virtual void Next() { + assert(Valid()); + ParseNextKey(); + } + + virtual void Prev() { + assert(Valid()); + + // Scan backwards to a restart point before current_ + const uint32_t original = current_; + while (GetRestartPoint(restart_index_) >= original) { + if (restart_index_ == 0) { + // No more entries + current_ = restarts_; + restart_index_ = num_restarts_; + return; + } + restart_index_--; + } + + SeekToRestartPoint(restart_index_); + do { + // Loop until end of current entry hits the start of original entry + } while (ParseNextKey() && NextEntryOffset() < original); + } + + virtual void Seek(const Slice& target) { + // Binary search in restart array to find the last restart point + // with a key < target + uint32_t left = 0; + uint32_t right = num_restarts_ - 1; + while (left < right) { + uint32_t mid = (left + right + 1) / 2; + uint32_t region_offset = GetRestartPoint(mid); + uint32_t shared, non_shared, value_length; + const char* key_ptr = + DecodeEntry(data_ + region_offset, data_ + restarts_, &shared, + &non_shared, &value_length); + if (key_ptr == nullptr || (shared != 0)) { + CorruptionError(); + return; + } + Slice mid_key(key_ptr, non_shared); + if (Compare(mid_key, target) < 0) { + // Key at "mid" is smaller than "target". Therefore all + // blocks before "mid" are uninteresting. + left = mid; + } else { + // Key at "mid" is >= "target". Therefore all blocks at or + // after "mid" are uninteresting. + right = mid - 1; + } + } + + // Linear search (within restart block) for first key >= target + SeekToRestartPoint(left); + while (true) { + if (!ParseNextKey()) { + return; + } + if (Compare(key_, target) >= 0) { + return; + } + } + } + + virtual void SeekToFirst() { + SeekToRestartPoint(0); + ParseNextKey(); + } + + virtual void SeekToLast() { + SeekToRestartPoint(num_restarts_ - 1); + while (ParseNextKey() && NextEntryOffset() < restarts_) { + // Keep skipping + } + } + + private: + void CorruptionError() { + current_ = restarts_; + restart_index_ = num_restarts_; + status_ = Status::Corruption("bad entry in block"); + key_.clear(); + value_.clear(); + } + + bool ParseNextKey() { + current_ = NextEntryOffset(); + const char* p = data_ + current_; + const char* limit = data_ + restarts_; // Restarts come right after data + if (p >= limit) { + // No more entries to return. Mark as invalid. + current_ = restarts_; + restart_index_ = num_restarts_; + return false; + } + + // Decode next entry + uint32_t shared, non_shared, value_length; + p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); + if (p == nullptr || key_.size() < shared) { + CorruptionError(); + return false; + } else { + key_.resize(shared); + key_.append(p, non_shared); + value_ = Slice(p + non_shared, value_length); + while (restart_index_ + 1 < num_restarts_ && + GetRestartPoint(restart_index_ + 1) < current_) { + ++restart_index_; + } + return true; + } + } +}; + +Iterator* Block::NewIterator(const Comparator* comparator) { + if (size_ < sizeof(uint32_t)) { + return NewErrorIterator(Status::Corruption("bad block contents")); + } + const uint32_t num_restarts = NumRestarts(); + if (num_restarts == 0) { + return NewEmptyIterator(); + } else { + return new Iter(comparator, data_, restart_offset_, num_restarts); + } +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/block.h b/MyExperiences copy/Pods/leveldb-library/table/block.h new file mode 100644 index 00000000..c8f1f7b4 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/block.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_H_ + +#include +#include + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct BlockContents; +class Comparator; + +class Block { + public: + // Initialize the block with the specified contents. + explicit Block(const BlockContents& contents); + + Block(const Block&) = delete; + Block& operator=(const Block&) = delete; + + ~Block(); + + size_t size() const { return size_; } + Iterator* NewIterator(const Comparator* comparator); + + private: + class Iter; + + uint32_t NumRestarts() const; + + const char* data_; + size_t size_; + uint32_t restart_offset_; // Offset in data_ of restart array + bool owned_; // Block owns data_[] +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/block_builder.cc b/MyExperiences copy/Pods/leveldb-library/table/block_builder.cc new file mode 100644 index 00000000..f7cb1b0a --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/block_builder.cc @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// BlockBuilder generates blocks where keys are prefix-compressed: +// +// When we store a key, we drop the prefix shared with the previous +// string. This helps reduce the space requirement significantly. +// Furthermore, once every K keys, we do not apply the prefix +// compression and store the entire key. We call this a "restart +// point". The tail end of the block stores the offsets of all of the +// restart points, and can be used to do a binary search when looking +// for a particular key. Values are stored as-is (without compression) +// immediately following the corresponding key. +// +// An entry for a particular key-value pair has the form: +// shared_bytes: varint32 +// unshared_bytes: varint32 +// value_length: varint32 +// key_delta: char[unshared_bytes] +// value: char[value_length] +// shared_bytes == 0 for restart points. +// +// The trailer of the block has the form: +// restarts: uint32[num_restarts] +// num_restarts: uint32 +// restarts[i] contains the offset within the block of the ith restart point. + +#include "table/block_builder.h" + +#include + +#include + +#include "leveldb/comparator.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" + +namespace leveldb { + +BlockBuilder::BlockBuilder(const Options* options) + : options_(options), restarts_(), counter_(0), finished_(false) { + assert(options->block_restart_interval >= 1); + restarts_.push_back(0); // First restart point is at offset 0 +} + +void BlockBuilder::Reset() { + buffer_.clear(); + restarts_.clear(); + restarts_.push_back(0); // First restart point is at offset 0 + counter_ = 0; + finished_ = false; + last_key_.clear(); +} + +size_t BlockBuilder::CurrentSizeEstimate() const { + return (buffer_.size() + // Raw data buffer + restarts_.size() * sizeof(uint32_t) + // Restart array + sizeof(uint32_t)); // Restart array length +} + +Slice BlockBuilder::Finish() { + // Append restart array + for (size_t i = 0; i < restarts_.size(); i++) { + PutFixed32(&buffer_, restarts_[i]); + } + PutFixed32(&buffer_, restarts_.size()); + finished_ = true; + return Slice(buffer_); +} + +void BlockBuilder::Add(const Slice& key, const Slice& value) { + Slice last_key_piece(last_key_); + assert(!finished_); + assert(counter_ <= options_->block_restart_interval); + assert(buffer_.empty() // No values yet? + || options_->comparator->Compare(key, last_key_piece) > 0); + size_t shared = 0; + if (counter_ < options_->block_restart_interval) { + // See how much sharing to do with previous string + const size_t min_length = std::min(last_key_piece.size(), key.size()); + while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { + shared++; + } + } else { + // Restart compression + restarts_.push_back(buffer_.size()); + counter_ = 0; + } + const size_t non_shared = key.size() - shared; + + // Add "" to buffer_ + PutVarint32(&buffer_, shared); + PutVarint32(&buffer_, non_shared); + PutVarint32(&buffer_, value.size()); + + // Add string delta to buffer_ followed by value + buffer_.append(key.data() + shared, non_shared); + buffer_.append(value.data(), value.size()); + + // Update state + last_key_.resize(shared); + last_key_.append(key.data() + shared, non_shared); + assert(Slice(last_key_) == key); + counter_++; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/block_builder.h b/MyExperiences copy/Pods/leveldb-library/table/block_builder.h new file mode 100644 index 00000000..f91f5e6d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/block_builder.h @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ + +#include + +#include + +#include "leveldb/slice.h" + +namespace leveldb { + +struct Options; + +class BlockBuilder { + public: + explicit BlockBuilder(const Options* options); + + BlockBuilder(const BlockBuilder&) = delete; + BlockBuilder& operator=(const BlockBuilder&) = delete; + + // Reset the contents as if the BlockBuilder was just constructed. + void Reset(); + + // REQUIRES: Finish() has not been called since the last call to Reset(). + // REQUIRES: key is larger than any previously added key + void Add(const Slice& key, const Slice& value); + + // Finish building the block and return a slice that refers to the + // block contents. The returned slice will remain valid for the + // lifetime of this builder or until Reset() is called. + Slice Finish(); + + // Returns an estimate of the current (uncompressed) size of the block + // we are building. + size_t CurrentSizeEstimate() const; + + // Return true iff no entries have been added since the last Reset() + bool empty() const { return buffer_.empty(); } + + private: + const Options* options_; + std::string buffer_; // Destination buffer + std::vector restarts_; // Restart points + int counter_; // Number of entries emitted since restart + bool finished_; // Has Finish() been called? + std::string last_key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/filter_block.cc b/MyExperiences copy/Pods/leveldb-library/table/filter_block.cc new file mode 100644 index 00000000..09ec0094 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/filter_block.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" + +namespace leveldb { + +// See doc/table_format.md for an explanation of the filter block format. + +// Generate new filter every 2KB of data +static const size_t kFilterBaseLg = 11; +static const size_t kFilterBase = 1 << kFilterBaseLg; + +FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) + : policy_(policy) {} + +void FilterBlockBuilder::StartBlock(uint64_t block_offset) { + uint64_t filter_index = (block_offset / kFilterBase); + assert(filter_index >= filter_offsets_.size()); + while (filter_index > filter_offsets_.size()) { + GenerateFilter(); + } +} + +void FilterBlockBuilder::AddKey(const Slice& key) { + Slice k = key; + start_.push_back(keys_.size()); + keys_.append(k.data(), k.size()); +} + +Slice FilterBlockBuilder::Finish() { + if (!start_.empty()) { + GenerateFilter(); + } + + // Append array of per-filter offsets + const uint32_t array_offset = result_.size(); + for (size_t i = 0; i < filter_offsets_.size(); i++) { + PutFixed32(&result_, filter_offsets_[i]); + } + + PutFixed32(&result_, array_offset); + result_.push_back(kFilterBaseLg); // Save encoding parameter in result + return Slice(result_); +} + +void FilterBlockBuilder::GenerateFilter() { + const size_t num_keys = start_.size(); + if (num_keys == 0) { + // Fast path if there are no keys for this filter + filter_offsets_.push_back(result_.size()); + return; + } + + // Make list of keys from flattened key structure + start_.push_back(keys_.size()); // Simplify length computation + tmp_keys_.resize(num_keys); + for (size_t i = 0; i < num_keys; i++) { + const char* base = keys_.data() + start_[i]; + size_t length = start_[i + 1] - start_[i]; + tmp_keys_[i] = Slice(base, length); + } + + // Generate filter for current set of keys and append to result_. + filter_offsets_.push_back(result_.size()); + policy_->CreateFilter(&tmp_keys_[0], static_cast(num_keys), &result_); + + tmp_keys_.clear(); + keys_.clear(); + start_.clear(); +} + +FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, + const Slice& contents) + : policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) { + size_t n = contents.size(); + if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array + base_lg_ = contents[n - 1]; + uint32_t last_word = DecodeFixed32(contents.data() + n - 5); + if (last_word > n - 5) return; + data_ = contents.data(); + offset_ = data_ + last_word; + num_ = (n - 5 - last_word) / 4; +} + +bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { + uint64_t index = block_offset >> base_lg_; + if (index < num_) { + uint32_t start = DecodeFixed32(offset_ + index * 4); + uint32_t limit = DecodeFixed32(offset_ + index * 4 + 4); + if (start <= limit && limit <= static_cast(offset_ - data_)) { + Slice filter = Slice(data_ + start, limit - start); + return policy_->KeyMayMatch(key, filter); + } else if (start == limit) { + // Empty filters do not match any keys + return false; + } + } + return true; // Errors are treated as potential matches +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/filter_block.h b/MyExperiences copy/Pods/leveldb-library/table/filter_block.h new file mode 100644 index 00000000..73b53992 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/filter_block.h @@ -0,0 +1,69 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A filter block is stored near the end of a Table file. It contains +// filters (e.g., bloom filters) for all data blocks in the table combined +// into a single filter block. + +#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ + +#include +#include + +#include +#include + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +class FilterPolicy; + +// A FilterBlockBuilder is used to construct all of the filters for a +// particular Table. It generates a single string which is stored as +// a special block in the Table. +// +// The sequence of calls to FilterBlockBuilder must match the regexp: +// (StartBlock AddKey*)* Finish +class FilterBlockBuilder { + public: + explicit FilterBlockBuilder(const FilterPolicy*); + + FilterBlockBuilder(const FilterBlockBuilder&) = delete; + FilterBlockBuilder& operator=(const FilterBlockBuilder&) = delete; + + void StartBlock(uint64_t block_offset); + void AddKey(const Slice& key); + Slice Finish(); + + private: + void GenerateFilter(); + + const FilterPolicy* policy_; + std::string keys_; // Flattened key contents + std::vector start_; // Starting index in keys_ of each key + std::string result_; // Filter data computed so far + std::vector tmp_keys_; // policy_->CreateFilter() argument + std::vector filter_offsets_; +}; + +class FilterBlockReader { + public: + // REQUIRES: "contents" and *policy must stay live while *this is live. + FilterBlockReader(const FilterPolicy* policy, const Slice& contents); + bool KeyMayMatch(uint64_t block_offset, const Slice& key); + + private: + const FilterPolicy* policy_; + const char* data_; // Pointer to filter data (at block-start) + const char* offset_; // Pointer to beginning of offset array (at block-end) + size_t num_; // Number of entries in offset array + size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/format.cc b/MyExperiences copy/Pods/leveldb-library/table/format.cc new file mode 100644 index 00000000..e1839779 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/format.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/format.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "table/block.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +void BlockHandle::EncodeTo(std::string* dst) const { + // Sanity check that all fields have been set + assert(offset_ != ~static_cast(0)); + assert(size_ != ~static_cast(0)); + PutVarint64(dst, offset_); + PutVarint64(dst, size_); +} + +Status BlockHandle::DecodeFrom(Slice* input) { + if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) { + return Status::OK(); + } else { + return Status::Corruption("bad block handle"); + } +} + +void Footer::EncodeTo(std::string* dst) const { + const size_t original_size = dst->size(); + metaindex_handle_.EncodeTo(dst); + index_handle_.EncodeTo(dst); + dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding + PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); + PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); + assert(dst->size() == original_size + kEncodedLength); + (void)original_size; // Disable unused variable warning. +} + +Status Footer::DecodeFrom(Slice* input) { + const char* magic_ptr = input->data() + kEncodedLength - 8; + const uint32_t magic_lo = DecodeFixed32(magic_ptr); + const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); + const uint64_t magic = ((static_cast(magic_hi) << 32) | + (static_cast(magic_lo))); + if (magic != kTableMagicNumber) { + return Status::Corruption("not an sstable (bad magic number)"); + } + + Status result = metaindex_handle_.DecodeFrom(input); + if (result.ok()) { + result = index_handle_.DecodeFrom(input); + } + if (result.ok()) { + // We skip over any leftover data (just padding for now) in "input" + const char* end = magic_ptr + 8; + *input = Slice(end, input->data() + input->size() - end); + } + return result; +} + +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result) { + result->data = Slice(); + result->cachable = false; + result->heap_allocated = false; + + // Read the block contents as well as the type/crc footer. + // See table_builder.cc for the code that built this structure. + size_t n = static_cast(handle.size()); + char* buf = new char[n + kBlockTrailerSize]; + Slice contents; + Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); + if (!s.ok()) { + delete[] buf; + return s; + } + if (contents.size() != n + kBlockTrailerSize) { + delete[] buf; + return Status::Corruption("truncated block read"); + } + + // Check the crc of the type and the block contents + const char* data = contents.data(); // Pointer to where Read put the data + if (options.verify_checksums) { + const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); + const uint32_t actual = crc32c::Value(data, n + 1); + if (actual != crc) { + delete[] buf; + s = Status::Corruption("block checksum mismatch"); + return s; + } + } + + switch (data[n]) { + case kNoCompression: + if (data != buf) { + // File implementation gave us pointer to some other data. + // Use it directly under the assumption that it will be live + // while the file is open. + delete[] buf; + result->data = Slice(data, n); + result->heap_allocated = false; + result->cachable = false; // Do not double-cache + } else { + result->data = Slice(buf, n); + result->heap_allocated = true; + result->cachable = true; + } + + // Ok + break; + case kSnappyCompression: { + size_t ulength = 0; + if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { + delete[] buf; + return Status::Corruption("corrupted compressed block contents"); + } + char* ubuf = new char[ulength]; + if (!port::Snappy_Uncompress(data, n, ubuf)) { + delete[] buf; + delete[] ubuf; + return Status::Corruption("corrupted compressed block contents"); + } + delete[] buf; + result->data = Slice(ubuf, ulength); + result->heap_allocated = true; + result->cachable = true; + break; + } + default: + delete[] buf; + return Status::Corruption("bad block type"); + } + + return Status::OK(); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/format.h b/MyExperiences copy/Pods/leveldb-library/table/format.h new file mode 100644 index 00000000..2ad145c3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/format.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ +#define STORAGE_LEVELDB_TABLE_FORMAT_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "leveldb/table_builder.h" + +namespace leveldb { + +class Block; +class RandomAccessFile; +struct ReadOptions; + +// BlockHandle is a pointer to the extent of a file that stores a data +// block or a meta block. +class BlockHandle { + public: + // Maximum encoding length of a BlockHandle + enum { kMaxEncodedLength = 10 + 10 }; + + BlockHandle(); + + // The offset of the block in the file. + uint64_t offset() const { return offset_; } + void set_offset(uint64_t offset) { offset_ = offset; } + + // The size of the stored block + uint64_t size() const { return size_; } + void set_size(uint64_t size) { size_ = size; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + uint64_t offset_; + uint64_t size_; +}; + +// Footer encapsulates the fixed information stored at the tail +// end of every table file. +class Footer { + public: + // Encoded length of a Footer. Note that the serialization of a + // Footer will always occupy exactly this many bytes. It consists + // of two block handles and a magic number. + enum { kEncodedLength = 2 * BlockHandle::kMaxEncodedLength + 8 }; + + Footer() {} + + // The block handle for the metaindex block of the table + const BlockHandle& metaindex_handle() const { return metaindex_handle_; } + void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } + + // The block handle for the index block of the table + const BlockHandle& index_handle() const { return index_handle_; } + void set_index_handle(const BlockHandle& h) { index_handle_ = h; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + BlockHandle metaindex_handle_; + BlockHandle index_handle_; +}; + +// kTableMagicNumber was picked by running +// echo http://code.google.com/p/leveldb/ | sha1sum +// and taking the leading 64 bits. +static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; + +// 1-byte type + 32-bit crc +static const size_t kBlockTrailerSize = 5; + +struct BlockContents { + Slice data; // Actual contents of data + bool cachable; // True iff data can be cached + bool heap_allocated; // True iff caller should delete[] data.data() +}; + +// Read the block identified by "handle" from "file". On failure +// return non-OK. On success fill *result and return OK. +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result); + +// Implementation details follow. Clients should ignore, + +inline BlockHandle::BlockHandle() + : offset_(~static_cast(0)), size_(~static_cast(0)) {} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/iterator.cc b/MyExperiences copy/Pods/leveldb-library/table/iterator.cc new file mode 100644 index 00000000..dfef083d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/iterator.cc @@ -0,0 +1,76 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/iterator.h" + +namespace leveldb { + +Iterator::Iterator() { + cleanup_head_.function = nullptr; + cleanup_head_.next = nullptr; +} + +Iterator::~Iterator() { + if (!cleanup_head_.IsEmpty()) { + cleanup_head_.Run(); + for (CleanupNode* node = cleanup_head_.next; node != nullptr;) { + node->Run(); + CleanupNode* next_node = node->next; + delete node; + node = next_node; + } + } +} + +void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { + assert(func != nullptr); + CleanupNode* node; + if (cleanup_head_.IsEmpty()) { + node = &cleanup_head_; + } else { + node = new CleanupNode(); + node->next = cleanup_head_.next; + cleanup_head_.next = node; + } + node->function = func; + node->arg1 = arg1; + node->arg2 = arg2; +} + +namespace { + +class EmptyIterator : public Iterator { + public: + EmptyIterator(const Status& s) : status_(s) {} + ~EmptyIterator() override = default; + + bool Valid() const override { return false; } + void Seek(const Slice& target) override {} + void SeekToFirst() override {} + void SeekToLast() override {} + void Next() override { assert(false); } + void Prev() override { assert(false); } + Slice key() const override { + assert(false); + return Slice(); + } + Slice value() const override { + assert(false); + return Slice(); + } + Status status() const override { return status_; } + + private: + Status status_; +}; + +} // anonymous namespace + +Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); } + +Iterator* NewErrorIterator(const Status& status) { + return new EmptyIterator(status); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/iterator_wrapper.h b/MyExperiences copy/Pods/leveldb-library/table/iterator_wrapper.h new file mode 100644 index 00000000..c2305725 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/iterator_wrapper.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ +#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ + +#include "leveldb/iterator.h" +#include "leveldb/slice.h" + +namespace leveldb { + +// A internal wrapper class with an interface similar to Iterator that +// caches the valid() and key() results for an underlying iterator. +// This can help avoid virtual function calls and also gives better +// cache locality. +class IteratorWrapper { + public: + IteratorWrapper() : iter_(nullptr), valid_(false) {} + explicit IteratorWrapper(Iterator* iter) : iter_(nullptr) { Set(iter); } + ~IteratorWrapper() { delete iter_; } + Iterator* iter() const { return iter_; } + + // Takes ownership of "iter" and will delete it when destroyed, or + // when Set() is invoked again. + void Set(Iterator* iter) { + delete iter_; + iter_ = iter; + if (iter_ == nullptr) { + valid_ = false; + } else { + Update(); + } + } + + // Iterator interface methods + bool Valid() const { return valid_; } + Slice key() const { + assert(Valid()); + return key_; + } + Slice value() const { + assert(Valid()); + return iter_->value(); + } + // Methods below require iter() != nullptr + Status status() const { + assert(iter_); + return iter_->status(); + } + void Next() { + assert(iter_); + iter_->Next(); + Update(); + } + void Prev() { + assert(iter_); + iter_->Prev(); + Update(); + } + void Seek(const Slice& k) { + assert(iter_); + iter_->Seek(k); + Update(); + } + void SeekToFirst() { + assert(iter_); + iter_->SeekToFirst(); + Update(); + } + void SeekToLast() { + assert(iter_); + iter_->SeekToLast(); + Update(); + } + + private: + void Update() { + valid_ = iter_->Valid(); + if (valid_) { + key_ = iter_->key(); + } + } + + Iterator* iter_; + bool valid_; + Slice key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/merger.cc b/MyExperiences copy/Pods/leveldb-library/table/merger.cc new file mode 100644 index 00000000..1bbc6cfd --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/merger.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/merger.h" + +#include "leveldb/comparator.h" +#include "leveldb/iterator.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { +class MergingIterator : public Iterator { + public: + MergingIterator(const Comparator* comparator, Iterator** children, int n) + : comparator_(comparator), + children_(new IteratorWrapper[n]), + n_(n), + current_(nullptr), + direction_(kForward) { + for (int i = 0; i < n; i++) { + children_[i].Set(children[i]); + } + } + + virtual ~MergingIterator() { delete[] children_; } + + virtual bool Valid() const { return (current_ != nullptr); } + + virtual void SeekToFirst() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToFirst(); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void SeekToLast() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToLast(); + } + FindLargest(); + direction_ = kReverse; + } + + virtual void Seek(const Slice& target) { + for (int i = 0; i < n_; i++) { + children_[i].Seek(target); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void Next() { + assert(Valid()); + + // Ensure that all children are positioned after key(). + // If we are moving in the forward direction, it is already + // true for all of the non-current_ children since current_ is + // the smallest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kForward) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid() && + comparator_->Compare(key(), child->key()) == 0) { + child->Next(); + } + } + } + direction_ = kForward; + } + + current_->Next(); + FindSmallest(); + } + + virtual void Prev() { + assert(Valid()); + + // Ensure that all children are positioned before key(). + // If we are moving in the reverse direction, it is already + // true for all of the non-current_ children since current_ is + // the largest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kReverse) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid()) { + // Child is at first entry >= key(). Step back one to be < key() + child->Prev(); + } else { + // Child has no entries >= key(). Position at last entry. + child->SeekToLast(); + } + } + } + direction_ = kReverse; + } + + current_->Prev(); + FindLargest(); + } + + virtual Slice key() const { + assert(Valid()); + return current_->key(); + } + + virtual Slice value() const { + assert(Valid()); + return current_->value(); + } + + virtual Status status() const { + Status status; + for (int i = 0; i < n_; i++) { + status = children_[i].status(); + if (!status.ok()) { + break; + } + } + return status; + } + + private: + // Which direction is the iterator moving? + enum Direction { kForward, kReverse }; + + void FindSmallest(); + void FindLargest(); + + // We might want to use a heap in case there are lots of children. + // For now we use a simple array since we expect a very small number + // of children in leveldb. + const Comparator* comparator_; + IteratorWrapper* children_; + int n_; + IteratorWrapper* current_; + Direction direction_; +}; + +void MergingIterator::FindSmallest() { + IteratorWrapper* smallest = nullptr; + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (smallest == nullptr) { + smallest = child; + } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { + smallest = child; + } + } + } + current_ = smallest; +} + +void MergingIterator::FindLargest() { + IteratorWrapper* largest = nullptr; + for (int i = n_ - 1; i >= 0; i--) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (largest == nullptr) { + largest = child; + } else if (comparator_->Compare(child->key(), largest->key()) > 0) { + largest = child; + } + } + } + current_ = largest; +} +} // namespace + +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n) { + assert(n >= 0); + if (n == 0) { + return NewEmptyIterator(); + } else if (n == 1) { + return children[0]; + } else { + return new MergingIterator(comparator, children, n); + } +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/merger.h b/MyExperiences copy/Pods/leveldb-library/table/merger.h new file mode 100644 index 00000000..41cedc52 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/merger.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ +#define STORAGE_LEVELDB_TABLE_MERGER_H_ + +namespace leveldb { + +class Comparator; +class Iterator; + +// Return an iterator that provided the union of the data in +// children[0,n-1]. Takes ownership of the child iterators and +// will delete them when the result iterator is deleted. +// +// The result does no duplicate suppression. I.e., if a particular +// key is present in K child iterators, it will be yielded K times. +// +// REQUIRES: n >= 0 +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/table/table.cc b/MyExperiences copy/Pods/leveldb-library/table/table.cc new file mode 100644 index 00000000..b07bc88c --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/table.cc @@ -0,0 +1,273 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" + +namespace leveldb { + +struct Table::Rep { + ~Rep() { + delete filter; + delete[] filter_data; + delete index_block; + } + + Options options; + Status status; + RandomAccessFile* file; + uint64_t cache_id; + FilterBlockReader* filter; + const char* filter_data; + + BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer + Block* index_block; +}; + +Status Table::Open(const Options& options, RandomAccessFile* file, + uint64_t size, Table** table) { + *table = nullptr; + if (size < Footer::kEncodedLength) { + return Status::Corruption("file is too short to be an sstable"); + } + + char footer_space[Footer::kEncodedLength]; + Slice footer_input; + Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, + &footer_input, footer_space); + if (!s.ok()) return s; + + Footer footer; + s = footer.DecodeFrom(&footer_input); + if (!s.ok()) return s; + + // Read the index block + BlockContents index_block_contents; + if (s.ok()) { + ReadOptions opt; + if (options.paranoid_checks) { + opt.verify_checksums = true; + } + s = ReadBlock(file, opt, footer.index_handle(), &index_block_contents); + } + + if (s.ok()) { + // We've successfully read the footer and the index block: we're + // ready to serve requests. + Block* index_block = new Block(index_block_contents); + Rep* rep = new Table::Rep; + rep->options = options; + rep->file = file; + rep->metaindex_handle = footer.metaindex_handle(); + rep->index_block = index_block; + rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0); + rep->filter_data = nullptr; + rep->filter = nullptr; + *table = new Table(rep); + (*table)->ReadMeta(footer); + } + + return s; +} + +void Table::ReadMeta(const Footer& footer) { + if (rep_->options.filter_policy == nullptr) { + return; // Do not need any metadata + } + + // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates + // it is an empty block. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents contents; + if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) { + // Do not propagate errors since meta info is not needed for operation + return; + } + Block* meta = new Block(contents); + + Iterator* iter = meta->NewIterator(BytewiseComparator()); + std::string key = "filter."; + key.append(rep_->options.filter_policy->Name()); + iter->Seek(key); + if (iter->Valid() && iter->key() == Slice(key)) { + ReadFilter(iter->value()); + } + delete iter; + delete meta; +} + +void Table::ReadFilter(const Slice& filter_handle_value) { + Slice v = filter_handle_value; + BlockHandle filter_handle; + if (!filter_handle.DecodeFrom(&v).ok()) { + return; + } + + // We might want to unify with ReadBlock() if we start + // requiring checksum verification in Table::Open. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents block; + if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) { + return; + } + if (block.heap_allocated) { + rep_->filter_data = block.data.data(); // Will need to delete later + } + rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); +} + +Table::~Table() { delete rep_; } + +static void DeleteBlock(void* arg, void* ignored) { + delete reinterpret_cast(arg); +} + +static void DeleteCachedBlock(const Slice& key, void* value) { + Block* block = reinterpret_cast(value); + delete block; +} + +static void ReleaseBlock(void* arg, void* h) { + Cache* cache = reinterpret_cast(arg); + Cache::Handle* handle = reinterpret_cast(h); + cache->Release(handle); +} + +// Convert an index iterator value (i.e., an encoded BlockHandle) +// into an iterator over the contents of the corresponding block. +Iterator* Table::BlockReader(void* arg, const ReadOptions& options, + const Slice& index_value) { + Table* table = reinterpret_cast(arg); + Cache* block_cache = table->rep_->options.block_cache; + Block* block = nullptr; + Cache::Handle* cache_handle = nullptr; + + BlockHandle handle; + Slice input = index_value; + Status s = handle.DecodeFrom(&input); + // We intentionally allow extra stuff in index_value so that we + // can add more features in the future. + + if (s.ok()) { + BlockContents contents; + if (block_cache != nullptr) { + char cache_key_buffer[16]; + EncodeFixed64(cache_key_buffer, table->rep_->cache_id); + EncodeFixed64(cache_key_buffer + 8, handle.offset()); + Slice key(cache_key_buffer, sizeof(cache_key_buffer)); + cache_handle = block_cache->Lookup(key); + if (cache_handle != nullptr) { + block = reinterpret_cast(block_cache->Value(cache_handle)); + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + if (contents.cachable && options.fill_cache) { + cache_handle = block_cache->Insert(key, block, block->size(), + &DeleteCachedBlock); + } + } + } + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + } + } + } + + Iterator* iter; + if (block != nullptr) { + iter = block->NewIterator(table->rep_->options.comparator); + if (cache_handle == nullptr) { + iter->RegisterCleanup(&DeleteBlock, block, nullptr); + } else { + iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); + } + } else { + iter = NewErrorIterator(s); + } + return iter; +} + +Iterator* Table::NewIterator(const ReadOptions& options) const { + return NewTwoLevelIterator( + rep_->index_block->NewIterator(rep_->options.comparator), + &Table::BlockReader, const_cast(this), options); +} + +Status Table::InternalGet(const ReadOptions& options, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Status s; + Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); + iiter->Seek(k); + if (iiter->Valid()) { + Slice handle_value = iiter->value(); + FilterBlockReader* filter = rep_->filter; + BlockHandle handle; + if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() && + !filter->KeyMayMatch(handle.offset(), k)) { + // Not found + } else { + Iterator* block_iter = BlockReader(this, options, iiter->value()); + block_iter->Seek(k); + if (block_iter->Valid()) { + (*handle_result)(arg, block_iter->key(), block_iter->value()); + } + s = block_iter->status(); + delete block_iter; + } + } + if (s.ok()) { + s = iiter->status(); + } + delete iiter; + return s; +} + +uint64_t Table::ApproximateOffsetOf(const Slice& key) const { + Iterator* index_iter = + rep_->index_block->NewIterator(rep_->options.comparator); + index_iter->Seek(key); + uint64_t result; + if (index_iter->Valid()) { + BlockHandle handle; + Slice input = index_iter->value(); + Status s = handle.DecodeFrom(&input); + if (s.ok()) { + result = handle.offset(); + } else { + // Strange: we can't decode the block handle in the index block. + // We'll just return the offset of the metaindex block, which is + // close to the whole file size for this case. + result = rep_->metaindex_handle.offset(); + } + } else { + // key is past the last key in the file. Approximate the offset + // by returning the offset of the metaindex block (which is + // right near the end of the file). + result = rep_->metaindex_handle.offset(); + } + delete index_iter; + return result; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/table_builder.cc b/MyExperiences copy/Pods/leveldb-library/table/table_builder.cc new file mode 100644 index 00000000..278febf9 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/table_builder.cc @@ -0,0 +1,265 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table_builder.h" + +#include + +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block_builder.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +struct TableBuilder::Rep { + Rep(const Options& opt, WritableFile* f) + : options(opt), + index_block_options(opt), + file(f), + offset(0), + data_block(&options), + index_block(&index_block_options), + num_entries(0), + closed(false), + filter_block(opt.filter_policy == nullptr + ? nullptr + : new FilterBlockBuilder(opt.filter_policy)), + pending_index_entry(false) { + index_block_options.block_restart_interval = 1; + } + + Options options; + Options index_block_options; + WritableFile* file; + uint64_t offset; + Status status; + BlockBuilder data_block; + BlockBuilder index_block; + std::string last_key; + int64_t num_entries; + bool closed; // Either Finish() or Abandon() has been called. + FilterBlockBuilder* filter_block; + + // We do not emit the index entry for a block until we have seen the + // first key for the next data block. This allows us to use shorter + // keys in the index block. For example, consider a block boundary + // between the keys "the quick brown fox" and "the who". We can use + // "the r" as the key for the index block entry since it is >= all + // entries in the first block and < all entries in subsequent + // blocks. + // + // Invariant: r->pending_index_entry is true only if data_block is empty. + bool pending_index_entry; + BlockHandle pending_handle; // Handle to add to index block + + std::string compressed_output; +}; + +TableBuilder::TableBuilder(const Options& options, WritableFile* file) + : rep_(new Rep(options, file)) { + if (rep_->filter_block != nullptr) { + rep_->filter_block->StartBlock(0); + } +} + +TableBuilder::~TableBuilder() { + assert(rep_->closed); // Catch errors where caller forgot to call Finish() + delete rep_->filter_block; + delete rep_; +} + +Status TableBuilder::ChangeOptions(const Options& options) { + // Note: if more fields are added to Options, update + // this function to catch changes that should not be allowed to + // change in the middle of building a Table. + if (options.comparator != rep_->options.comparator) { + return Status::InvalidArgument("changing comparator while building table"); + } + + // Note that any live BlockBuilders point to rep_->options and therefore + // will automatically pick up the updated options. + rep_->options = options; + rep_->index_block_options = options; + rep_->index_block_options.block_restart_interval = 1; + return Status::OK(); +} + +void TableBuilder::Add(const Slice& key, const Slice& value) { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->num_entries > 0) { + assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); + } + + if (r->pending_index_entry) { + assert(r->data_block.empty()); + r->options.comparator->FindShortestSeparator(&r->last_key, key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + + if (r->filter_block != nullptr) { + r->filter_block->AddKey(key); + } + + r->last_key.assign(key.data(), key.size()); + r->num_entries++; + r->data_block.Add(key, value); + + const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); + if (estimated_block_size >= r->options.block_size) { + Flush(); + } +} + +void TableBuilder::Flush() { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->data_block.empty()) return; + assert(!r->pending_index_entry); + WriteBlock(&r->data_block, &r->pending_handle); + if (ok()) { + r->pending_index_entry = true; + r->status = r->file->Flush(); + } + if (r->filter_block != nullptr) { + r->filter_block->StartBlock(r->offset); + } +} + +void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { + // File format contains a sequence of blocks where each block has: + // block_data: uint8[n] + // type: uint8 + // crc: uint32 + assert(ok()); + Rep* r = rep_; + Slice raw = block->Finish(); + + Slice block_contents; + CompressionType type = r->options.compression; + // TODO(postrelease): Support more compression options: zlib? + switch (type) { + case kNoCompression: + block_contents = raw; + break; + + case kSnappyCompression: { + std::string* compressed = &r->compressed_output; + if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && + compressed->size() < raw.size() - (raw.size() / 8u)) { + block_contents = *compressed; + } else { + // Snappy not supported, or compressed less than 12.5%, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + } + WriteRawBlock(block_contents, type, handle); + r->compressed_output.clear(); + block->Reset(); +} + +void TableBuilder::WriteRawBlock(const Slice& block_contents, + CompressionType type, BlockHandle* handle) { + Rep* r = rep_; + handle->set_offset(r->offset); + handle->set_size(block_contents.size()); + r->status = r->file->Append(block_contents); + if (r->status.ok()) { + char trailer[kBlockTrailerSize]; + trailer[0] = type; + uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); + crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type + EncodeFixed32(trailer + 1, crc32c::Mask(crc)); + r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); + if (r->status.ok()) { + r->offset += block_contents.size() + kBlockTrailerSize; + } + } +} + +Status TableBuilder::status() const { return rep_->status; } + +Status TableBuilder::Finish() { + Rep* r = rep_; + Flush(); + assert(!r->closed); + r->closed = true; + + BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; + + // Write filter block + if (ok() && r->filter_block != nullptr) { + WriteRawBlock(r->filter_block->Finish(), kNoCompression, + &filter_block_handle); + } + + // Write metaindex block + if (ok()) { + BlockBuilder meta_index_block(&r->options); + if (r->filter_block != nullptr) { + // Add mapping from "filter.Name" to location of filter data + std::string key = "filter."; + key.append(r->options.filter_policy->Name()); + std::string handle_encoding; + filter_block_handle.EncodeTo(&handle_encoding); + meta_index_block.Add(key, handle_encoding); + } + + // TODO(postrelease): Add stats and other meta blocks + WriteBlock(&meta_index_block, &metaindex_block_handle); + } + + // Write index block + if (ok()) { + if (r->pending_index_entry) { + r->options.comparator->FindShortSuccessor(&r->last_key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + WriteBlock(&r->index_block, &index_block_handle); + } + + // Write footer + if (ok()) { + Footer footer; + footer.set_metaindex_handle(metaindex_block_handle); + footer.set_index_handle(index_block_handle); + std::string footer_encoding; + footer.EncodeTo(&footer_encoding); + r->status = r->file->Append(footer_encoding); + if (r->status.ok()) { + r->offset += footer_encoding.size(); + } + } + return r->status; +} + +void TableBuilder::Abandon() { + Rep* r = rep_; + assert(!r->closed); + r->closed = true; +} + +uint64_t TableBuilder::NumEntries() const { return rep_->num_entries; } + +uint64_t TableBuilder::FileSize() const { return rep_->offset; } + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.cc b/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.cc new file mode 100644 index 00000000..5340a4d3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.cc @@ -0,0 +1,171 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/two_level_iterator.h" + +#include "leveldb/table.h" +#include "table/block.h" +#include "table/format.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); + +class TwoLevelIterator : public Iterator { + public: + TwoLevelIterator(Iterator* index_iter, BlockFunction block_function, + void* arg, const ReadOptions& options); + + virtual ~TwoLevelIterator(); + + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + virtual void Next(); + virtual void Prev(); + + virtual bool Valid() const { return data_iter_.Valid(); } + virtual Slice key() const { + assert(Valid()); + return data_iter_.key(); + } + virtual Slice value() const { + assert(Valid()); + return data_iter_.value(); + } + virtual Status status() const { + // It'd be nice if status() returned a const Status& instead of a Status + if (!index_iter_.status().ok()) { + return index_iter_.status(); + } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) { + return data_iter_.status(); + } else { + return status_; + } + } + + private: + void SaveError(const Status& s) { + if (status_.ok() && !s.ok()) status_ = s; + } + void SkipEmptyDataBlocksForward(); + void SkipEmptyDataBlocksBackward(); + void SetDataIterator(Iterator* data_iter); + void InitDataBlock(); + + BlockFunction block_function_; + void* arg_; + const ReadOptions options_; + Status status_; + IteratorWrapper index_iter_; + IteratorWrapper data_iter_; // May be nullptr + // If data_iter_ is non-null, then "data_block_handle_" holds the + // "index_value" passed to block_function_ to create the data_iter_. + std::string data_block_handle_; +}; + +TwoLevelIterator::TwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) + : block_function_(block_function), + arg_(arg), + options_(options), + index_iter_(index_iter), + data_iter_(nullptr) {} + +TwoLevelIterator::~TwoLevelIterator() {} + +void TwoLevelIterator::Seek(const Slice& target) { + index_iter_.Seek(target); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.Seek(target); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToFirst() { + index_iter_.SeekToFirst(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToLast() { + index_iter_.SeekToLast(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::Next() { + assert(Valid()); + data_iter_.Next(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::Prev() { + assert(Valid()); + data_iter_.Prev(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::SkipEmptyDataBlocksForward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Next(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + } +} + +void TwoLevelIterator::SkipEmptyDataBlocksBackward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Prev(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + } +} + +void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { + if (data_iter_.iter() != nullptr) SaveError(data_iter_.status()); + data_iter_.Set(data_iter); +} + +void TwoLevelIterator::InitDataBlock() { + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + } else { + Slice handle = index_iter_.value(); + if (data_iter_.iter() != nullptr && + handle.compare(data_block_handle_) == 0) { + // data_iter_ is already constructed with this iterator, so + // no need to change anything + } else { + Iterator* iter = (*block_function_)(arg_, options_, handle); + data_block_handle_.assign(handle.data(), handle.size()); + SetDataIterator(iter); + } + } +} + +} // namespace + +Iterator* NewTwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) { + return new TwoLevelIterator(index_iter, block_function, arg, options); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.h b/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.h new file mode 100644 index 00000000..81ffe809 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/table/two_level_iterator.h @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ +#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct ReadOptions; + +// Return a new two level iterator. A two-level iterator contains an +// index iterator whose values point to a sequence of blocks where +// each block is itself a sequence of key,value pairs. The returned +// two-level iterator yields the concatenation of all key/value pairs +// in the sequence of blocks. Takes ownership of "index_iter" and +// will delete it when no longer needed. +// +// Uses a supplied function to convert an index_iter value into +// an iterator over the contents of the corresponding block. +Iterator* NewTwoLevelIterator( + Iterator* index_iter, + Iterator* (*block_function)(void* arg, const ReadOptions& options, + const Slice& index_value), + void* arg, const ReadOptions& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/arena.cc b/MyExperiences copy/Pods/leveldb-library/util/arena.cc new file mode 100644 index 00000000..46e3b2eb --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/arena.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" + +namespace leveldb { + +static const int kBlockSize = 4096; + +Arena::Arena() + : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {} + +Arena::~Arena() { + for (size_t i = 0; i < blocks_.size(); i++) { + delete[] blocks_[i]; + } +} + +char* Arena::AllocateFallback(size_t bytes) { + if (bytes > kBlockSize / 4) { + // Object is more than a quarter of our block size. Allocate it separately + // to avoid wasting too much space in leftover bytes. + char* result = AllocateNewBlock(bytes); + return result; + } + + // We waste the remaining space in the current block. + alloc_ptr_ = AllocateNewBlock(kBlockSize); + alloc_bytes_remaining_ = kBlockSize; + + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; +} + +char* Arena::AllocateAligned(size_t bytes) { + const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; + static_assert((align & (align - 1)) == 0, + "Pointer size should be a power of 2"); + size_t current_mod = reinterpret_cast(alloc_ptr_) & (align - 1); + size_t slop = (current_mod == 0 ? 0 : align - current_mod); + size_t needed = bytes + slop; + char* result; + if (needed <= alloc_bytes_remaining_) { + result = alloc_ptr_ + slop; + alloc_ptr_ += needed; + alloc_bytes_remaining_ -= needed; + } else { + // AllocateFallback always returned aligned memory + result = AllocateFallback(bytes); + } + assert((reinterpret_cast(result) & (align - 1)) == 0); + return result; +} + +char* Arena::AllocateNewBlock(size_t block_bytes) { + char* result = new char[block_bytes]; + blocks_.push_back(result); + memory_usage_.fetch_add(block_bytes + sizeof(char*), + std::memory_order_relaxed); + return result; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/arena.h b/MyExperiences copy/Pods/leveldb-library/util/arena.h new file mode 100644 index 00000000..68fc55d4 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/arena.h @@ -0,0 +1,71 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ +#define STORAGE_LEVELDB_UTIL_ARENA_H_ + +#include +#include +#include +#include +#include + +namespace leveldb { + +class Arena { + public: + Arena(); + + Arena(const Arena&) = delete; + Arena& operator=(const Arena&) = delete; + + ~Arena(); + + // Return a pointer to a newly allocated memory block of "bytes" bytes. + char* Allocate(size_t bytes); + + // Allocate memory with the normal alignment guarantees provided by malloc. + char* AllocateAligned(size_t bytes); + + // Returns an estimate of the total memory usage of data allocated + // by the arena. + size_t MemoryUsage() const { + return memory_usage_.load(std::memory_order_relaxed); + } + + private: + char* AllocateFallback(size_t bytes); + char* AllocateNewBlock(size_t block_bytes); + + // Allocation state + char* alloc_ptr_; + size_t alloc_bytes_remaining_; + + // Array of new[] allocated memory blocks + std::vector blocks_; + + // Total memory usage of the arena. + // + // TODO(costan): This member is accessed via atomics, but the others are + // accessed without any locking. Is this OK? + std::atomic memory_usage_; +}; + +inline char* Arena::Allocate(size_t bytes) { + // The semantics of what to return are a bit messy if we allow + // 0-byte allocations, so we disallow them here (we don't need + // them for our internal use). + assert(bytes > 0); + if (bytes <= alloc_bytes_remaining_) { + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; + } + return AllocateFallback(bytes); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/bloom.cc b/MyExperiences copy/Pods/leveldb-library/util/bloom.cc new file mode 100644 index 00000000..7f974649 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/bloom.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +namespace { +static uint32_t BloomHash(const Slice& key) { + return Hash(key.data(), key.size(), 0xbc9f1d34); +} + +class BloomFilterPolicy : public FilterPolicy { + public: + explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) { + // We intentionally round down to reduce probing cost a little bit + k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2) + if (k_ < 1) k_ = 1; + if (k_ > 30) k_ = 30; + } + + virtual const char* Name() const { return "leveldb.BuiltinBloomFilter2"; } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Compute bloom filter size (in both bits and bytes) + size_t bits = n * bits_per_key_; + + // For small n, we can see a very high false positive rate. Fix it + // by enforcing a minimum bloom filter length. + if (bits < 64) bits = 64; + + size_t bytes = (bits + 7) / 8; + bits = bytes * 8; + + const size_t init_size = dst->size(); + dst->resize(init_size + bytes, 0); + dst->push_back(static_cast(k_)); // Remember # of probes in filter + char* array = &(*dst)[init_size]; + for (int i = 0; i < n; i++) { + // Use double-hashing to generate a sequence of hash values. + // See analysis in [Kirsch,Mitzenmacher 2006]. + uint32_t h = BloomHash(keys[i]); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k_; j++) { + const uint32_t bitpos = h % bits; + array[bitpos / 8] |= (1 << (bitpos % 8)); + h += delta; + } + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { + const size_t len = bloom_filter.size(); + if (len < 2) return false; + + const char* array = bloom_filter.data(); + const size_t bits = (len - 1) * 8; + + // Use the encoded k so that we can read filters generated by + // bloom filters created using different parameters. + const size_t k = array[len - 1]; + if (k > 30) { + // Reserved for potentially new encodings for short bloom filters. + // Consider it a match. + return true; + } + + uint32_t h = BloomHash(key); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k; j++) { + const uint32_t bitpos = h % bits; + if ((array[bitpos / 8] & (1 << (bitpos % 8))) == 0) return false; + h += delta; + } + return true; + } + + private: + size_t bits_per_key_; + size_t k_; +}; +} // namespace + +const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { + return new BloomFilterPolicy(bits_per_key); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/cache.cc b/MyExperiences copy/Pods/leveldb-library/util/cache.cc new file mode 100644 index 00000000..0f801ccc --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/cache.cc @@ -0,0 +1,400 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/cache.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/hash.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Cache::~Cache() {} + +namespace { + +// LRU cache implementation +// +// Cache entries have an "in_cache" boolean indicating whether the cache has a +// reference on the entry. The only ways that this can become false without the +// entry being passed to its "deleter" are via Erase(), via Insert() when +// an element with a duplicate key is inserted, or on destruction of the cache. +// +// The cache keeps two linked lists of items in the cache. All items in the +// cache are in one list or the other, and never both. Items still referenced +// by clients but erased from the cache are in neither list. The lists are: +// - in-use: contains the items currently referenced by clients, in no +// particular order. (This list is used for invariant checking. If we +// removed the check, elements that would otherwise be on this list could be +// left as disconnected singleton lists.) +// - LRU: contains the items not currently referenced by clients, in LRU order +// Elements are moved between these lists by the Ref() and Unref() methods, +// when they detect an element in the cache acquiring or losing its only +// external reference. + +// An entry is a variable length heap-allocated structure. Entries +// are kept in a circular doubly linked list ordered by access time. +struct LRUHandle { + void* value; + void (*deleter)(const Slice&, void* value); + LRUHandle* next_hash; + LRUHandle* next; + LRUHandle* prev; + size_t charge; // TODO(opt): Only allow uint32_t? + size_t key_length; + bool in_cache; // Whether entry is in the cache. + uint32_t refs; // References, including cache reference, if present. + uint32_t hash; // Hash of key(); used for fast sharding and comparisons + char key_data[1]; // Beginning of key + + Slice key() const { + // next_ is only equal to this if the LRU handle is the list head of an + // empty list. List heads never have meaningful keys. + assert(next != this); + + return Slice(key_data, key_length); + } +}; + +// We provide our own simple hash table since it removes a whole bunch +// of porting hacks and is also faster than some of the built-in hash +// table implementations in some of the compiler/runtime combinations +// we have tested. E.g., readrandom speeds up by ~5% over the g++ +// 4.4.3's builtin hashtable. +class HandleTable { + public: + HandleTable() : length_(0), elems_(0), list_(nullptr) { Resize(); } + ~HandleTable() { delete[] list_; } + + LRUHandle* Lookup(const Slice& key, uint32_t hash) { + return *FindPointer(key, hash); + } + + LRUHandle* Insert(LRUHandle* h) { + LRUHandle** ptr = FindPointer(h->key(), h->hash); + LRUHandle* old = *ptr; + h->next_hash = (old == nullptr ? nullptr : old->next_hash); + *ptr = h; + if (old == nullptr) { + ++elems_; + if (elems_ > length_) { + // Since each cache entry is fairly large, we aim for a small + // average linked list length (<= 1). + Resize(); + } + } + return old; + } + + LRUHandle* Remove(const Slice& key, uint32_t hash) { + LRUHandle** ptr = FindPointer(key, hash); + LRUHandle* result = *ptr; + if (result != nullptr) { + *ptr = result->next_hash; + --elems_; + } + return result; + } + + private: + // The table consists of an array of buckets where each bucket is + // a linked list of cache entries that hash into the bucket. + uint32_t length_; + uint32_t elems_; + LRUHandle** list_; + + // Return a pointer to slot that points to a cache entry that + // matches key/hash. If there is no such cache entry, return a + // pointer to the trailing slot in the corresponding linked list. + LRUHandle** FindPointer(const Slice& key, uint32_t hash) { + LRUHandle** ptr = &list_[hash & (length_ - 1)]; + while (*ptr != nullptr && ((*ptr)->hash != hash || key != (*ptr)->key())) { + ptr = &(*ptr)->next_hash; + } + return ptr; + } + + void Resize() { + uint32_t new_length = 4; + while (new_length < elems_) { + new_length *= 2; + } + LRUHandle** new_list = new LRUHandle*[new_length]; + memset(new_list, 0, sizeof(new_list[0]) * new_length); + uint32_t count = 0; + for (uint32_t i = 0; i < length_; i++) { + LRUHandle* h = list_[i]; + while (h != nullptr) { + LRUHandle* next = h->next_hash; + uint32_t hash = h->hash; + LRUHandle** ptr = &new_list[hash & (new_length - 1)]; + h->next_hash = *ptr; + *ptr = h; + h = next; + count++; + } + } + assert(elems_ == count); + delete[] list_; + list_ = new_list; + length_ = new_length; + } +}; + +// A single shard of sharded cache. +class LRUCache { + public: + LRUCache(); + ~LRUCache(); + + // Separate from constructor so caller can easily make an array of LRUCache + void SetCapacity(size_t capacity) { capacity_ = capacity; } + + // Like Cache methods, but with an extra "hash" parameter. + Cache::Handle* Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, void* value)); + Cache::Handle* Lookup(const Slice& key, uint32_t hash); + void Release(Cache::Handle* handle); + void Erase(const Slice& key, uint32_t hash); + void Prune(); + size_t TotalCharge() const { + MutexLock l(&mutex_); + return usage_; + } + + private: + void LRU_Remove(LRUHandle* e); + void LRU_Append(LRUHandle* list, LRUHandle* e); + void Ref(LRUHandle* e); + void Unref(LRUHandle* e); + bool FinishErase(LRUHandle* e) EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Initialized before use. + size_t capacity_; + + // mutex_ protects the following state. + mutable port::Mutex mutex_; + size_t usage_ GUARDED_BY(mutex_); + + // Dummy head of LRU list. + // lru.prev is newest entry, lru.next is oldest entry. + // Entries have refs==1 and in_cache==true. + LRUHandle lru_ GUARDED_BY(mutex_); + + // Dummy head of in-use list. + // Entries are in use by clients, and have refs >= 2 and in_cache==true. + LRUHandle in_use_ GUARDED_BY(mutex_); + + HandleTable table_ GUARDED_BY(mutex_); +}; + +LRUCache::LRUCache() : capacity_(0), usage_(0) { + // Make empty circular linked lists. + lru_.next = &lru_; + lru_.prev = &lru_; + in_use_.next = &in_use_; + in_use_.prev = &in_use_; +} + +LRUCache::~LRUCache() { + assert(in_use_.next == &in_use_); // Error if caller has an unreleased handle + for (LRUHandle* e = lru_.next; e != &lru_;) { + LRUHandle* next = e->next; + assert(e->in_cache); + e->in_cache = false; + assert(e->refs == 1); // Invariant of lru_ list. + Unref(e); + e = next; + } +} + +void LRUCache::Ref(LRUHandle* e) { + if (e->refs == 1 && e->in_cache) { // If on lru_ list, move to in_use_ list. + LRU_Remove(e); + LRU_Append(&in_use_, e); + } + e->refs++; +} + +void LRUCache::Unref(LRUHandle* e) { + assert(e->refs > 0); + e->refs--; + if (e->refs == 0) { // Deallocate. + assert(!e->in_cache); + (*e->deleter)(e->key(), e->value); + free(e); + } else if (e->in_cache && e->refs == 1) { + // No longer in use; move to lru_ list. + LRU_Remove(e); + LRU_Append(&lru_, e); + } +} + +void LRUCache::LRU_Remove(LRUHandle* e) { + e->next->prev = e->prev; + e->prev->next = e->next; +} + +void LRUCache::LRU_Append(LRUHandle* list, LRUHandle* e) { + // Make "e" newest entry by inserting just before *list + e->next = list; + e->prev = list->prev; + e->prev->next = e; + e->next->prev = e; +} + +Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Lookup(key, hash); + if (e != nullptr) { + Ref(e); + } + return reinterpret_cast(e); +} + +void LRUCache::Release(Cache::Handle* handle) { + MutexLock l(&mutex_); + Unref(reinterpret_cast(handle)); +} + +Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, + void* value)) { + MutexLock l(&mutex_); + + LRUHandle* e = + reinterpret_cast(malloc(sizeof(LRUHandle) - 1 + key.size())); + e->value = value; + e->deleter = deleter; + e->charge = charge; + e->key_length = key.size(); + e->hash = hash; + e->in_cache = false; + e->refs = 1; // for the returned handle. + memcpy(e->key_data, key.data(), key.size()); + + if (capacity_ > 0) { + e->refs++; // for the cache's reference. + e->in_cache = true; + LRU_Append(&in_use_, e); + usage_ += charge; + FinishErase(table_.Insert(e)); + } else { // don't cache. (capacity_==0 is supported and turns off caching.) + // next is read by key() in an assert, so it must be initialized + e->next = nullptr; + } + while (usage_ > capacity_ && lru_.next != &lru_) { + LRUHandle* old = lru_.next; + assert(old->refs == 1); + bool erased = FinishErase(table_.Remove(old->key(), old->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } + + return reinterpret_cast(e); +} + +// If e != nullptr, finish removing *e from the cache; it has already been +// removed from the hash table. Return whether e != nullptr. +bool LRUCache::FinishErase(LRUHandle* e) { + if (e != nullptr) { + assert(e->in_cache); + LRU_Remove(e); + e->in_cache = false; + usage_ -= e->charge; + Unref(e); + } + return e != nullptr; +} + +void LRUCache::Erase(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + FinishErase(table_.Remove(key, hash)); +} + +void LRUCache::Prune() { + MutexLock l(&mutex_); + while (lru_.next != &lru_) { + LRUHandle* e = lru_.next; + assert(e->refs == 1); + bool erased = FinishErase(table_.Remove(e->key(), e->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } +} + +static const int kNumShardBits = 4; +static const int kNumShards = 1 << kNumShardBits; + +class ShardedLRUCache : public Cache { + private: + LRUCache shard_[kNumShards]; + port::Mutex id_mutex_; + uint64_t last_id_; + + static inline uint32_t HashSlice(const Slice& s) { + return Hash(s.data(), s.size(), 0); + } + + static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); } + + public: + explicit ShardedLRUCache(size_t capacity) : last_id_(0) { + const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards; + for (int s = 0; s < kNumShards; s++) { + shard_[s].SetCapacity(per_shard); + } + } + virtual ~ShardedLRUCache() {} + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); + } + virtual Handle* Lookup(const Slice& key) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Lookup(key, hash); + } + virtual void Release(Handle* handle) { + LRUHandle* h = reinterpret_cast(handle); + shard_[Shard(h->hash)].Release(handle); + } + virtual void Erase(const Slice& key) { + const uint32_t hash = HashSlice(key); + shard_[Shard(hash)].Erase(key, hash); + } + virtual void* Value(Handle* handle) { + return reinterpret_cast(handle)->value; + } + virtual uint64_t NewId() { + MutexLock l(&id_mutex_); + return ++(last_id_); + } + virtual void Prune() { + for (int s = 0; s < kNumShards; s++) { + shard_[s].Prune(); + } + } + virtual size_t TotalCharge() const { + size_t total = 0; + for (int s = 0; s < kNumShards; s++) { + total += shard_[s].TotalCharge(); + } + return total; + } +}; + +} // end anonymous namespace + +Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); } + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/coding.cc b/MyExperiences copy/Pods/leveldb-library/util/coding.cc new file mode 100644 index 00000000..e2089df9 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/coding.cc @@ -0,0 +1,192 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +namespace leveldb { + +void EncodeFixed32(char* dst, uint32_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + } +} + +void EncodeFixed64(char* dst, uint64_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + dst[4] = (value >> 32) & 0xff; + dst[5] = (value >> 40) & 0xff; + dst[6] = (value >> 48) & 0xff; + dst[7] = (value >> 56) & 0xff; + } +} + +void PutFixed32(std::string* dst, uint32_t value) { + char buf[sizeof(value)]; + EncodeFixed32(buf, value); + dst->append(buf, sizeof(buf)); +} + +void PutFixed64(std::string* dst, uint64_t value) { + char buf[sizeof(value)]; + EncodeFixed64(buf, value); + dst->append(buf, sizeof(buf)); +} + +char* EncodeVarint32(char* dst, uint32_t v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(dst); + static const int B = 128; + if (v < (1 << 7)) { + *(ptr++) = v; + } else if (v < (1 << 14)) { + *(ptr++) = v | B; + *(ptr++) = v >> 7; + } else if (v < (1 << 21)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = v >> 14; + } else if (v < (1 << 28)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = v >> 21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = (v >> 21) | B; + *(ptr++) = v >> 28; + } + return reinterpret_cast(ptr); +} + +void PutVarint32(std::string* dst, uint32_t v) { + char buf[5]; + char* ptr = EncodeVarint32(buf, v); + dst->append(buf, ptr - buf); +} + +char* EncodeVarint64(char* dst, uint64_t v) { + static const int B = 128; + unsigned char* ptr = reinterpret_cast(dst); + while (v >= B) { + *(ptr++) = v | B; + v >>= 7; + } + *(ptr++) = static_cast(v); + return reinterpret_cast(ptr); +} + +void PutVarint64(std::string* dst, uint64_t v) { + char buf[10]; + char* ptr = EncodeVarint64(buf, v); + dst->append(buf, ptr - buf); +} + +void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { + PutVarint32(dst, value.size()); + dst->append(value.data(), value.size()); +} + +int VarintLength(uint64_t v) { + int len = 1; + while (v >= 128) { + v >>= 7; + len++; + } + return len; +} + +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value) { + uint32_t result = 0; + for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { + uint32_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint32(Slice* input, uint32_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint32Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { + uint64_t result = 0; + for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { + uint64_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint64(Slice* input, uint64_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint64Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetLengthPrefixedSlice(const char* p, const char* limit, + Slice* result) { + uint32_t len; + p = GetVarint32Ptr(p, limit, &len); + if (p == nullptr) return nullptr; + if (p + len > limit) return nullptr; + *result = Slice(p, len); + return p + len; +} + +bool GetLengthPrefixedSlice(Slice* input, Slice* result) { + uint32_t len; + if (GetVarint32(input, &len) && input->size() >= len) { + *result = Slice(input->data(), len); + input->remove_prefix(len); + return true; + } else { + return false; + } +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/coding.h b/MyExperiences copy/Pods/leveldb-library/util/coding.h new file mode 100644 index 00000000..d9eeaa31 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/coding.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Endian-neutral encoding: +// * Fixed-length numbers are encoded with least-significant byte first +// * In addition we support variable length "varint" encoding +// * Strings are encoded prefixed by their length in varint format + +#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ +#define STORAGE_LEVELDB_UTIL_CODING_H_ + +#include +#include + +#include + +#include "leveldb/slice.h" +#include "port/port.h" + +namespace leveldb { + +// Standard Put... routines append to a string +void PutFixed32(std::string* dst, uint32_t value); +void PutFixed64(std::string* dst, uint64_t value); +void PutVarint32(std::string* dst, uint32_t value); +void PutVarint64(std::string* dst, uint64_t value); +void PutLengthPrefixedSlice(std::string* dst, const Slice& value); + +// Standard Get... routines parse a value from the beginning of a Slice +// and advance the slice past the parsed value. +bool GetVarint32(Slice* input, uint32_t* value); +bool GetVarint64(Slice* input, uint64_t* value); +bool GetLengthPrefixedSlice(Slice* input, Slice* result); + +// Pointer-based variants of GetVarint... These either store a value +// in *v and return a pointer just past the parsed value, or return +// nullptr on error. These routines only look at bytes in the range +// [p..limit-1] +const char* GetVarint32Ptr(const char* p, const char* limit, uint32_t* v); +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* v); + +// Returns the length of the varint32 or varint64 encoding of "v" +int VarintLength(uint64_t v); + +// Lower-level versions of Put... that write directly into a character buffer +// REQUIRES: dst has enough space for the value being written +void EncodeFixed32(char* dst, uint32_t value); +void EncodeFixed64(char* dst, uint64_t value); + +// Lower-level versions of Put... that write directly into a character buffer +// and return a pointer just past the last byte written. +// REQUIRES: dst has enough space for the value being written +char* EncodeVarint32(char* dst, uint32_t value); +char* EncodeVarint64(char* dst, uint64_t value); + +// Lower-level versions of Get... that read directly from a character buffer +// without any bounds checking. + +inline uint32_t DecodeFixed32(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint32_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) | + (static_cast(static_cast(ptr[1])) << 8) | + (static_cast(static_cast(ptr[2])) << 16) | + (static_cast(static_cast(ptr[3])) << 24)); + } +} + +inline uint64_t DecodeFixed64(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint64_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + uint64_t lo = DecodeFixed32(ptr); + uint64_t hi = DecodeFixed32(ptr + 4); + return (hi << 32) | lo; + } +} + +// Internal routine for use by fallback path of GetVarint32Ptr +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value); +inline const char* GetVarint32Ptr(const char* p, const char* limit, + uint32_t* value) { + if (p < limit) { + uint32_t result = *(reinterpret_cast(p)); + if ((result & 128) == 0) { + *value = result; + return p + 1; + } + } + return GetVarint32PtrFallback(p, limit, value); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/comparator.cc b/MyExperiences copy/Pods/leveldb-library/util/comparator.cc new file mode 100644 index 00000000..26d1eb3b --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/comparator.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/comparator.h" +#include "leveldb/slice.h" +#include "util/logging.h" +#include "util/no_destructor.h" + +namespace leveldb { + +Comparator::~Comparator() {} + +namespace { +class BytewiseComparatorImpl : public Comparator { + public: + BytewiseComparatorImpl() {} + + virtual const char* Name() const { return "leveldb.BytewiseComparator"; } + + virtual int Compare(const Slice& a, const Slice& b) const { + return a.compare(b); + } + + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Find length of common prefix + size_t min_length = std::min(start->size(), limit.size()); + size_t diff_index = 0; + while ((diff_index < min_length) && + ((*start)[diff_index] == limit[diff_index])) { + diff_index++; + } + + if (diff_index >= min_length) { + // Do not shorten if one string is a prefix of the other + } else { + uint8_t diff_byte = static_cast((*start)[diff_index]); + if (diff_byte < static_cast(0xff) && + diff_byte + 1 < static_cast(limit[diff_index])) { + (*start)[diff_index]++; + start->resize(diff_index + 1); + assert(Compare(*start, limit) < 0); + } + } + } + + virtual void FindShortSuccessor(std::string* key) const { + // Find first character that can be incremented + size_t n = key->size(); + for (size_t i = 0; i < n; i++) { + const uint8_t byte = (*key)[i]; + if (byte != static_cast(0xff)) { + (*key)[i] = byte + 1; + key->resize(i + 1); + return; + } + } + // *key is a run of 0xffs. Leave it alone. + } +}; +} // namespace + +const Comparator* BytewiseComparator() { + static NoDestructor singleton; + return singleton.get(); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/crc32c.cc b/MyExperiences copy/Pods/leveldb-library/util/crc32c.cc new file mode 100644 index 00000000..c2e61f7d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/crc32c.cc @@ -0,0 +1,380 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c. + +#include "util/crc32c.h" + +#include +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { +namespace crc32c { + +namespace { + +const uint32_t kByteExtensionTable[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, + 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, + 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, + 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, + 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, + 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, + 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, + 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, + 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, + 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, + 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, + 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, + 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, + 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, + 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, + 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, + 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, + 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, + 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, + 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, + 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, + 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351}; + +const uint32_t kStrideExtensionTable0[256] = { + 0x00000000, 0x30d23865, 0x61a470ca, 0x517648af, 0xc348e194, 0xf39ad9f1, + 0xa2ec915e, 0x923ea93b, 0x837db5d9, 0xb3af8dbc, 0xe2d9c513, 0xd20bfd76, + 0x4035544d, 0x70e76c28, 0x21912487, 0x11431ce2, 0x03171d43, 0x33c52526, + 0x62b36d89, 0x526155ec, 0xc05ffcd7, 0xf08dc4b2, 0xa1fb8c1d, 0x9129b478, + 0x806aa89a, 0xb0b890ff, 0xe1ced850, 0xd11ce035, 0x4322490e, 0x73f0716b, + 0x228639c4, 0x125401a1, 0x062e3a86, 0x36fc02e3, 0x678a4a4c, 0x57587229, + 0xc566db12, 0xf5b4e377, 0xa4c2abd8, 0x941093bd, 0x85538f5f, 0xb581b73a, + 0xe4f7ff95, 0xd425c7f0, 0x461b6ecb, 0x76c956ae, 0x27bf1e01, 0x176d2664, + 0x053927c5, 0x35eb1fa0, 0x649d570f, 0x544f6f6a, 0xc671c651, 0xf6a3fe34, + 0xa7d5b69b, 0x97078efe, 0x8644921c, 0xb696aa79, 0xe7e0e2d6, 0xd732dab3, + 0x450c7388, 0x75de4bed, 0x24a80342, 0x147a3b27, 0x0c5c750c, 0x3c8e4d69, + 0x6df805c6, 0x5d2a3da3, 0xcf149498, 0xffc6acfd, 0xaeb0e452, 0x9e62dc37, + 0x8f21c0d5, 0xbff3f8b0, 0xee85b01f, 0xde57887a, 0x4c692141, 0x7cbb1924, + 0x2dcd518b, 0x1d1f69ee, 0x0f4b684f, 0x3f99502a, 0x6eef1885, 0x5e3d20e0, + 0xcc0389db, 0xfcd1b1be, 0xada7f911, 0x9d75c174, 0x8c36dd96, 0xbce4e5f3, + 0xed92ad5c, 0xdd409539, 0x4f7e3c02, 0x7fac0467, 0x2eda4cc8, 0x1e0874ad, + 0x0a724f8a, 0x3aa077ef, 0x6bd63f40, 0x5b040725, 0xc93aae1e, 0xf9e8967b, + 0xa89eded4, 0x984ce6b1, 0x890ffa53, 0xb9ddc236, 0xe8ab8a99, 0xd879b2fc, + 0x4a471bc7, 0x7a9523a2, 0x2be36b0d, 0x1b315368, 0x096552c9, 0x39b76aac, + 0x68c12203, 0x58131a66, 0xca2db35d, 0xfaff8b38, 0xab89c397, 0x9b5bfbf2, + 0x8a18e710, 0xbacadf75, 0xebbc97da, 0xdb6eafbf, 0x49500684, 0x79823ee1, + 0x28f4764e, 0x18264e2b, 0x18b8ea18, 0x286ad27d, 0x791c9ad2, 0x49cea2b7, + 0xdbf00b8c, 0xeb2233e9, 0xba547b46, 0x8a864323, 0x9bc55fc1, 0xab1767a4, + 0xfa612f0b, 0xcab3176e, 0x588dbe55, 0x685f8630, 0x3929ce9f, 0x09fbf6fa, + 0x1baff75b, 0x2b7dcf3e, 0x7a0b8791, 0x4ad9bff4, 0xd8e716cf, 0xe8352eaa, + 0xb9436605, 0x89915e60, 0x98d24282, 0xa8007ae7, 0xf9763248, 0xc9a40a2d, + 0x5b9aa316, 0x6b489b73, 0x3a3ed3dc, 0x0aecebb9, 0x1e96d09e, 0x2e44e8fb, + 0x7f32a054, 0x4fe09831, 0xddde310a, 0xed0c096f, 0xbc7a41c0, 0x8ca879a5, + 0x9deb6547, 0xad395d22, 0xfc4f158d, 0xcc9d2de8, 0x5ea384d3, 0x6e71bcb6, + 0x3f07f419, 0x0fd5cc7c, 0x1d81cddd, 0x2d53f5b8, 0x7c25bd17, 0x4cf78572, + 0xdec92c49, 0xee1b142c, 0xbf6d5c83, 0x8fbf64e6, 0x9efc7804, 0xae2e4061, + 0xff5808ce, 0xcf8a30ab, 0x5db49990, 0x6d66a1f5, 0x3c10e95a, 0x0cc2d13f, + 0x14e49f14, 0x2436a771, 0x7540efde, 0x4592d7bb, 0xd7ac7e80, 0xe77e46e5, + 0xb6080e4a, 0x86da362f, 0x97992acd, 0xa74b12a8, 0xf63d5a07, 0xc6ef6262, + 0x54d1cb59, 0x6403f33c, 0x3575bb93, 0x05a783f6, 0x17f38257, 0x2721ba32, + 0x7657f29d, 0x4685caf8, 0xd4bb63c3, 0xe4695ba6, 0xb51f1309, 0x85cd2b6c, + 0x948e378e, 0xa45c0feb, 0xf52a4744, 0xc5f87f21, 0x57c6d61a, 0x6714ee7f, + 0x3662a6d0, 0x06b09eb5, 0x12caa592, 0x22189df7, 0x736ed558, 0x43bced3d, + 0xd1824406, 0xe1507c63, 0xb02634cc, 0x80f40ca9, 0x91b7104b, 0xa165282e, + 0xf0136081, 0xc0c158e4, 0x52fff1df, 0x622dc9ba, 0x335b8115, 0x0389b970, + 0x11ddb8d1, 0x210f80b4, 0x7079c81b, 0x40abf07e, 0xd2955945, 0xe2476120, + 0xb331298f, 0x83e311ea, 0x92a00d08, 0xa272356d, 0xf3047dc2, 0xc3d645a7, + 0x51e8ec9c, 0x613ad4f9, 0x304c9c56, 0x009ea433}; + +const uint32_t kStrideExtensionTable1[256] = { + 0x00000000, 0x54075546, 0xa80eaa8c, 0xfc09ffca, 0x55f123e9, 0x01f676af, + 0xfdff8965, 0xa9f8dc23, 0xabe247d2, 0xffe51294, 0x03eced5e, 0x57ebb818, + 0xfe13643b, 0xaa14317d, 0x561dceb7, 0x021a9bf1, 0x5228f955, 0x062fac13, + 0xfa2653d9, 0xae21069f, 0x07d9dabc, 0x53de8ffa, 0xafd77030, 0xfbd02576, + 0xf9cabe87, 0xadcdebc1, 0x51c4140b, 0x05c3414d, 0xac3b9d6e, 0xf83cc828, + 0x043537e2, 0x503262a4, 0xa451f2aa, 0xf056a7ec, 0x0c5f5826, 0x58580d60, + 0xf1a0d143, 0xa5a78405, 0x59ae7bcf, 0x0da92e89, 0x0fb3b578, 0x5bb4e03e, + 0xa7bd1ff4, 0xf3ba4ab2, 0x5a429691, 0x0e45c3d7, 0xf24c3c1d, 0xa64b695b, + 0xf6790bff, 0xa27e5eb9, 0x5e77a173, 0x0a70f435, 0xa3882816, 0xf78f7d50, + 0x0b86829a, 0x5f81d7dc, 0x5d9b4c2d, 0x099c196b, 0xf595e6a1, 0xa192b3e7, + 0x086a6fc4, 0x5c6d3a82, 0xa064c548, 0xf463900e, 0x4d4f93a5, 0x1948c6e3, + 0xe5413929, 0xb1466c6f, 0x18beb04c, 0x4cb9e50a, 0xb0b01ac0, 0xe4b74f86, + 0xe6add477, 0xb2aa8131, 0x4ea37efb, 0x1aa42bbd, 0xb35cf79e, 0xe75ba2d8, + 0x1b525d12, 0x4f550854, 0x1f676af0, 0x4b603fb6, 0xb769c07c, 0xe36e953a, + 0x4a964919, 0x1e911c5f, 0xe298e395, 0xb69fb6d3, 0xb4852d22, 0xe0827864, + 0x1c8b87ae, 0x488cd2e8, 0xe1740ecb, 0xb5735b8d, 0x497aa447, 0x1d7df101, + 0xe91e610f, 0xbd193449, 0x4110cb83, 0x15179ec5, 0xbcef42e6, 0xe8e817a0, + 0x14e1e86a, 0x40e6bd2c, 0x42fc26dd, 0x16fb739b, 0xeaf28c51, 0xbef5d917, + 0x170d0534, 0x430a5072, 0xbf03afb8, 0xeb04fafe, 0xbb36985a, 0xef31cd1c, + 0x133832d6, 0x473f6790, 0xeec7bbb3, 0xbac0eef5, 0x46c9113f, 0x12ce4479, + 0x10d4df88, 0x44d38ace, 0xb8da7504, 0xecdd2042, 0x4525fc61, 0x1122a927, + 0xed2b56ed, 0xb92c03ab, 0x9a9f274a, 0xce98720c, 0x32918dc6, 0x6696d880, + 0xcf6e04a3, 0x9b6951e5, 0x6760ae2f, 0x3367fb69, 0x317d6098, 0x657a35de, + 0x9973ca14, 0xcd749f52, 0x648c4371, 0x308b1637, 0xcc82e9fd, 0x9885bcbb, + 0xc8b7de1f, 0x9cb08b59, 0x60b97493, 0x34be21d5, 0x9d46fdf6, 0xc941a8b0, + 0x3548577a, 0x614f023c, 0x635599cd, 0x3752cc8b, 0xcb5b3341, 0x9f5c6607, + 0x36a4ba24, 0x62a3ef62, 0x9eaa10a8, 0xcaad45ee, 0x3eced5e0, 0x6ac980a6, + 0x96c07f6c, 0xc2c72a2a, 0x6b3ff609, 0x3f38a34f, 0xc3315c85, 0x973609c3, + 0x952c9232, 0xc12bc774, 0x3d2238be, 0x69256df8, 0xc0ddb1db, 0x94dae49d, + 0x68d31b57, 0x3cd44e11, 0x6ce62cb5, 0x38e179f3, 0xc4e88639, 0x90efd37f, + 0x39170f5c, 0x6d105a1a, 0x9119a5d0, 0xc51ef096, 0xc7046b67, 0x93033e21, + 0x6f0ac1eb, 0x3b0d94ad, 0x92f5488e, 0xc6f21dc8, 0x3afbe202, 0x6efcb744, + 0xd7d0b4ef, 0x83d7e1a9, 0x7fde1e63, 0x2bd94b25, 0x82219706, 0xd626c240, + 0x2a2f3d8a, 0x7e2868cc, 0x7c32f33d, 0x2835a67b, 0xd43c59b1, 0x803b0cf7, + 0x29c3d0d4, 0x7dc48592, 0x81cd7a58, 0xd5ca2f1e, 0x85f84dba, 0xd1ff18fc, + 0x2df6e736, 0x79f1b270, 0xd0096e53, 0x840e3b15, 0x7807c4df, 0x2c009199, + 0x2e1a0a68, 0x7a1d5f2e, 0x8614a0e4, 0xd213f5a2, 0x7beb2981, 0x2fec7cc7, + 0xd3e5830d, 0x87e2d64b, 0x73814645, 0x27861303, 0xdb8fecc9, 0x8f88b98f, + 0x267065ac, 0x727730ea, 0x8e7ecf20, 0xda799a66, 0xd8630197, 0x8c6454d1, + 0x706dab1b, 0x246afe5d, 0x8d92227e, 0xd9957738, 0x259c88f2, 0x719bddb4, + 0x21a9bf10, 0x75aeea56, 0x89a7159c, 0xdda040da, 0x74589cf9, 0x205fc9bf, + 0xdc563675, 0x88516333, 0x8a4bf8c2, 0xde4cad84, 0x2245524e, 0x76420708, + 0xdfbadb2b, 0x8bbd8e6d, 0x77b471a7, 0x23b324e1}; + +const uint32_t kStrideExtensionTable2[256] = { + 0x00000000, 0x678efd01, 0xcf1dfa02, 0xa8930703, 0x9bd782f5, 0xfc597ff4, + 0x54ca78f7, 0x334485f6, 0x3243731b, 0x55cd8e1a, 0xfd5e8919, 0x9ad07418, + 0xa994f1ee, 0xce1a0cef, 0x66890bec, 0x0107f6ed, 0x6486e636, 0x03081b37, + 0xab9b1c34, 0xcc15e135, 0xff5164c3, 0x98df99c2, 0x304c9ec1, 0x57c263c0, + 0x56c5952d, 0x314b682c, 0x99d86f2f, 0xfe56922e, 0xcd1217d8, 0xaa9cead9, + 0x020fedda, 0x658110db, 0xc90dcc6c, 0xae83316d, 0x0610366e, 0x619ecb6f, + 0x52da4e99, 0x3554b398, 0x9dc7b49b, 0xfa49499a, 0xfb4ebf77, 0x9cc04276, + 0x34534575, 0x53ddb874, 0x60993d82, 0x0717c083, 0xaf84c780, 0xc80a3a81, + 0xad8b2a5a, 0xca05d75b, 0x6296d058, 0x05182d59, 0x365ca8af, 0x51d255ae, + 0xf94152ad, 0x9ecfafac, 0x9fc85941, 0xf846a440, 0x50d5a343, 0x375b5e42, + 0x041fdbb4, 0x639126b5, 0xcb0221b6, 0xac8cdcb7, 0x97f7ee29, 0xf0791328, + 0x58ea142b, 0x3f64e92a, 0x0c206cdc, 0x6bae91dd, 0xc33d96de, 0xa4b36bdf, + 0xa5b49d32, 0xc23a6033, 0x6aa96730, 0x0d279a31, 0x3e631fc7, 0x59ede2c6, + 0xf17ee5c5, 0x96f018c4, 0xf371081f, 0x94fff51e, 0x3c6cf21d, 0x5be20f1c, + 0x68a68aea, 0x0f2877eb, 0xa7bb70e8, 0xc0358de9, 0xc1327b04, 0xa6bc8605, + 0x0e2f8106, 0x69a17c07, 0x5ae5f9f1, 0x3d6b04f0, 0x95f803f3, 0xf276fef2, + 0x5efa2245, 0x3974df44, 0x91e7d847, 0xf6692546, 0xc52da0b0, 0xa2a35db1, + 0x0a305ab2, 0x6dbea7b3, 0x6cb9515e, 0x0b37ac5f, 0xa3a4ab5c, 0xc42a565d, + 0xf76ed3ab, 0x90e02eaa, 0x387329a9, 0x5ffdd4a8, 0x3a7cc473, 0x5df23972, + 0xf5613e71, 0x92efc370, 0xa1ab4686, 0xc625bb87, 0x6eb6bc84, 0x09384185, + 0x083fb768, 0x6fb14a69, 0xc7224d6a, 0xa0acb06b, 0x93e8359d, 0xf466c89c, + 0x5cf5cf9f, 0x3b7b329e, 0x2a03aaa3, 0x4d8d57a2, 0xe51e50a1, 0x8290ada0, + 0xb1d42856, 0xd65ad557, 0x7ec9d254, 0x19472f55, 0x1840d9b8, 0x7fce24b9, + 0xd75d23ba, 0xb0d3debb, 0x83975b4d, 0xe419a64c, 0x4c8aa14f, 0x2b045c4e, + 0x4e854c95, 0x290bb194, 0x8198b697, 0xe6164b96, 0xd552ce60, 0xb2dc3361, + 0x1a4f3462, 0x7dc1c963, 0x7cc63f8e, 0x1b48c28f, 0xb3dbc58c, 0xd455388d, + 0xe711bd7b, 0x809f407a, 0x280c4779, 0x4f82ba78, 0xe30e66cf, 0x84809bce, + 0x2c139ccd, 0x4b9d61cc, 0x78d9e43a, 0x1f57193b, 0xb7c41e38, 0xd04ae339, + 0xd14d15d4, 0xb6c3e8d5, 0x1e50efd6, 0x79de12d7, 0x4a9a9721, 0x2d146a20, + 0x85876d23, 0xe2099022, 0x878880f9, 0xe0067df8, 0x48957afb, 0x2f1b87fa, + 0x1c5f020c, 0x7bd1ff0d, 0xd342f80e, 0xb4cc050f, 0xb5cbf3e2, 0xd2450ee3, + 0x7ad609e0, 0x1d58f4e1, 0x2e1c7117, 0x49928c16, 0xe1018b15, 0x868f7614, + 0xbdf4448a, 0xda7ab98b, 0x72e9be88, 0x15674389, 0x2623c67f, 0x41ad3b7e, + 0xe93e3c7d, 0x8eb0c17c, 0x8fb73791, 0xe839ca90, 0x40aacd93, 0x27243092, + 0x1460b564, 0x73ee4865, 0xdb7d4f66, 0xbcf3b267, 0xd972a2bc, 0xbefc5fbd, + 0x166f58be, 0x71e1a5bf, 0x42a52049, 0x252bdd48, 0x8db8da4b, 0xea36274a, + 0xeb31d1a7, 0x8cbf2ca6, 0x242c2ba5, 0x43a2d6a4, 0x70e65352, 0x1768ae53, + 0xbffba950, 0xd8755451, 0x74f988e6, 0x137775e7, 0xbbe472e4, 0xdc6a8fe5, + 0xef2e0a13, 0x88a0f712, 0x2033f011, 0x47bd0d10, 0x46bafbfd, 0x213406fc, + 0x89a701ff, 0xee29fcfe, 0xdd6d7908, 0xbae38409, 0x1270830a, 0x75fe7e0b, + 0x107f6ed0, 0x77f193d1, 0xdf6294d2, 0xb8ec69d3, 0x8ba8ec25, 0xec261124, + 0x44b51627, 0x233beb26, 0x223c1dcb, 0x45b2e0ca, 0xed21e7c9, 0x8aaf1ac8, + 0xb9eb9f3e, 0xde65623f, 0x76f6653c, 0x1178983d}; + +const uint32_t kStrideExtensionTable3[256] = { + 0x00000000, 0xf20c0dfe, 0xe1f46d0d, 0x13f860f3, 0xc604aceb, 0x3408a115, + 0x27f0c1e6, 0xd5fccc18, 0x89e52f27, 0x7be922d9, 0x6811422a, 0x9a1d4fd4, + 0x4fe183cc, 0xbded8e32, 0xae15eec1, 0x5c19e33f, 0x162628bf, 0xe42a2541, + 0xf7d245b2, 0x05de484c, 0xd0228454, 0x222e89aa, 0x31d6e959, 0xc3dae4a7, + 0x9fc30798, 0x6dcf0a66, 0x7e376a95, 0x8c3b676b, 0x59c7ab73, 0xabcba68d, + 0xb833c67e, 0x4a3fcb80, 0x2c4c517e, 0xde405c80, 0xcdb83c73, 0x3fb4318d, + 0xea48fd95, 0x1844f06b, 0x0bbc9098, 0xf9b09d66, 0xa5a97e59, 0x57a573a7, + 0x445d1354, 0xb6511eaa, 0x63add2b2, 0x91a1df4c, 0x8259bfbf, 0x7055b241, + 0x3a6a79c1, 0xc866743f, 0xdb9e14cc, 0x29921932, 0xfc6ed52a, 0x0e62d8d4, + 0x1d9ab827, 0xef96b5d9, 0xb38f56e6, 0x41835b18, 0x527b3beb, 0xa0773615, + 0x758bfa0d, 0x8787f7f3, 0x947f9700, 0x66739afe, 0x5898a2fc, 0xaa94af02, + 0xb96ccff1, 0x4b60c20f, 0x9e9c0e17, 0x6c9003e9, 0x7f68631a, 0x8d646ee4, + 0xd17d8ddb, 0x23718025, 0x3089e0d6, 0xc285ed28, 0x17792130, 0xe5752cce, + 0xf68d4c3d, 0x048141c3, 0x4ebe8a43, 0xbcb287bd, 0xaf4ae74e, 0x5d46eab0, + 0x88ba26a8, 0x7ab62b56, 0x694e4ba5, 0x9b42465b, 0xc75ba564, 0x3557a89a, + 0x26afc869, 0xd4a3c597, 0x015f098f, 0xf3530471, 0xe0ab6482, 0x12a7697c, + 0x74d4f382, 0x86d8fe7c, 0x95209e8f, 0x672c9371, 0xb2d05f69, 0x40dc5297, + 0x53243264, 0xa1283f9a, 0xfd31dca5, 0x0f3dd15b, 0x1cc5b1a8, 0xeec9bc56, + 0x3b35704e, 0xc9397db0, 0xdac11d43, 0x28cd10bd, 0x62f2db3d, 0x90fed6c3, + 0x8306b630, 0x710abbce, 0xa4f677d6, 0x56fa7a28, 0x45021adb, 0xb70e1725, + 0xeb17f41a, 0x191bf9e4, 0x0ae39917, 0xf8ef94e9, 0x2d1358f1, 0xdf1f550f, + 0xcce735fc, 0x3eeb3802, 0xb13145f8, 0x433d4806, 0x50c528f5, 0xa2c9250b, + 0x7735e913, 0x8539e4ed, 0x96c1841e, 0x64cd89e0, 0x38d46adf, 0xcad86721, + 0xd92007d2, 0x2b2c0a2c, 0xfed0c634, 0x0cdccbca, 0x1f24ab39, 0xed28a6c7, + 0xa7176d47, 0x551b60b9, 0x46e3004a, 0xb4ef0db4, 0x6113c1ac, 0x931fcc52, + 0x80e7aca1, 0x72eba15f, 0x2ef24260, 0xdcfe4f9e, 0xcf062f6d, 0x3d0a2293, + 0xe8f6ee8b, 0x1afae375, 0x09028386, 0xfb0e8e78, 0x9d7d1486, 0x6f711978, + 0x7c89798b, 0x8e857475, 0x5b79b86d, 0xa975b593, 0xba8dd560, 0x4881d89e, + 0x14983ba1, 0xe694365f, 0xf56c56ac, 0x07605b52, 0xd29c974a, 0x20909ab4, + 0x3368fa47, 0xc164f7b9, 0x8b5b3c39, 0x795731c7, 0x6aaf5134, 0x98a35cca, + 0x4d5f90d2, 0xbf539d2c, 0xacabfddf, 0x5ea7f021, 0x02be131e, 0xf0b21ee0, + 0xe34a7e13, 0x114673ed, 0xc4babff5, 0x36b6b20b, 0x254ed2f8, 0xd742df06, + 0xe9a9e704, 0x1ba5eafa, 0x085d8a09, 0xfa5187f7, 0x2fad4bef, 0xdda14611, + 0xce5926e2, 0x3c552b1c, 0x604cc823, 0x9240c5dd, 0x81b8a52e, 0x73b4a8d0, + 0xa64864c8, 0x54446936, 0x47bc09c5, 0xb5b0043b, 0xff8fcfbb, 0x0d83c245, + 0x1e7ba2b6, 0xec77af48, 0x398b6350, 0xcb876eae, 0xd87f0e5d, 0x2a7303a3, + 0x766ae09c, 0x8466ed62, 0x979e8d91, 0x6592806f, 0xb06e4c77, 0x42624189, + 0x519a217a, 0xa3962c84, 0xc5e5b67a, 0x37e9bb84, 0x2411db77, 0xd61dd689, + 0x03e11a91, 0xf1ed176f, 0xe215779c, 0x10197a62, 0x4c00995d, 0xbe0c94a3, + 0xadf4f450, 0x5ff8f9ae, 0x8a0435b6, 0x78083848, 0x6bf058bb, 0x99fc5545, + 0xd3c39ec5, 0x21cf933b, 0x3237f3c8, 0xc03bfe36, 0x15c7322e, 0xe7cb3fd0, + 0xf4335f23, 0x063f52dd, 0x5a26b1e2, 0xa82abc1c, 0xbbd2dcef, 0x49ded111, + 0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa}; + +// CRCs are pre- and post- conditioned by xoring with all ones. +static constexpr const uint32_t kCRC32Xor = static_cast(0xffffffffU); + +// Reads a little-endian 32-bit integer from a 32-bit-aligned buffer. +inline uint32_t ReadUint32LE(const uint8_t* buffer) { + return DecodeFixed32(reinterpret_cast(buffer)); +} + +// Returns the smallest address >= the given address that is aligned to N bytes. +// +// N must be a power of two. +template +constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) { + return reinterpret_cast( + (reinterpret_cast(pointer) + (N - 1)) & + ~static_cast(N - 1)); +} + +} // namespace + +// Determine if the CPU running this program can accelerate the CRC32C +// calculation. +static bool CanAccelerateCRC32C() { + // port::AcceleretedCRC32C returns zero when unable to accelerate. + static const char kTestCRCBuffer[] = "TestCRCBuffer"; + static const char kBufSize = sizeof(kTestCRCBuffer) - 1; + static const uint32_t kTestCRCValue = 0xdcbc59fa; + + return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue; +} + +uint32_t Extend(uint32_t crc, const char* data, size_t n) { + static bool accelerate = CanAccelerateCRC32C(); + if (accelerate) { + return port::AcceleratedCRC32C(crc, data, n); + } + + const uint8_t* p = reinterpret_cast(data); + const uint8_t* e = p + n; + uint32_t l = crc ^ kCRC32Xor; + +// Process one byte at a time. +#define STEP1 \ + do { \ + int c = (l & 0xff) ^ *p++; \ + l = kByteExtensionTable[c] ^ (l >> 8); \ + } while (0) + +// Process one of the 4 strides of 4-byte data. +#define STEP4(s) \ + do { \ + crc##s = ReadUint32LE(p + s * 4) ^ kStrideExtensionTable3[crc##s & 0xff] ^ \ + kStrideExtensionTable2[(crc##s >> 8) & 0xff] ^ \ + kStrideExtensionTable1[(crc##s >> 16) & 0xff] ^ \ + kStrideExtensionTable0[crc##s >> 24]; \ + } while (0) + +// Process a 16-byte swath of 4 strides, each of which has 4 bytes of data. +#define STEP16 \ + do { \ + STEP4(0); \ + STEP4(1); \ + STEP4(2); \ + STEP4(3); \ + p += 16; \ + } while (0) + +// Process 4 bytes that were already loaded into a word. +#define STEP4W(w) \ + do { \ + w ^= l; \ + for (size_t i = 0; i < 4; ++i) { \ + w = (w >> 8) ^ kByteExtensionTable[w & 0xff]; \ + } \ + l = w; \ + } while (0) + + // Point x at first 4-byte aligned byte in the buffer. This might be past the + // end of the buffer. + const uint8_t* x = RoundUp<4>(p); + if (x <= e) { + // Process bytes p is 4-byte aligned. + while (p != x) { + STEP1; + } + } + + if ((e - p) >= 16) { + // Load a 16-byte swath into the stride partial results. + uint32_t crc0 = ReadUint32LE(p + 0 * 4) ^ l; + uint32_t crc1 = ReadUint32LE(p + 1 * 4); + uint32_t crc2 = ReadUint32LE(p + 2 * 4); + uint32_t crc3 = ReadUint32LE(p + 3 * 4); + p += 16; + + // It is possible to get better speeds (at least on x86) by interleaving + // prefetching 256 bytes ahead with processing 64 bytes at a time. See the + // portable implementation in https://github.com/google/crc32c/. + + // Process one 16-byte swath at a time. + while ((e - p) >= 16) { + STEP16; + } + + // Advance one word at a time as far as possible. + while ((e - p) >= 4) { + STEP4(0); + uint32_t tmp = crc0; + crc0 = crc1; + crc1 = crc2; + crc2 = crc3; + crc3 = tmp; + p += 4; + } + + // Combine the 4 partial stride results. + l = 0; + STEP4W(crc0); + STEP4W(crc1); + STEP4W(crc2); + STEP4W(crc3); + } + + // Process the last few bytes. + while (p != e) { + STEP1; + } +#undef STEP4W +#undef STEP16 +#undef STEP4 +#undef STEP1 + return l ^ kCRC32Xor; +} + +} // namespace crc32c +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/crc32c.h b/MyExperiences copy/Pods/leveldb-library/util/crc32c.h new file mode 100644 index 00000000..98fabb0d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/crc32c.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ +#define STORAGE_LEVELDB_UTIL_CRC32C_H_ + +#include +#include + +namespace leveldb { +namespace crc32c { + +// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the +// crc32c of some string A. Extend() is often used to maintain the +// crc32c of a stream of data. +uint32_t Extend(uint32_t init_crc, const char* data, size_t n); + +// Return the crc32c of data[0,n-1] +inline uint32_t Value(const char* data, size_t n) { return Extend(0, data, n); } + +static const uint32_t kMaskDelta = 0xa282ead8ul; + +// Return a masked representation of crc. +// +// Motivation: it is problematic to compute the CRC of a string that +// contains embedded CRCs. Therefore we recommend that CRCs stored +// somewhere (e.g., in files) should be masked before being stored. +inline uint32_t Mask(uint32_t crc) { + // Rotate right by 15 bits and add a constant. + return ((crc >> 15) | (crc << 17)) + kMaskDelta; +} + +// Return the crc whose masked representation is masked_crc. +inline uint32_t Unmask(uint32_t masked_crc) { + uint32_t rot = masked_crc - kMaskDelta; + return ((rot >> 17) | (rot << 15)); +} + +} // namespace crc32c +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/env.cc b/MyExperiences copy/Pods/leveldb-library/util/env.cc new file mode 100644 index 00000000..6cd5f2e3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/env.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +namespace leveldb { + +Env::~Env() {} + +Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) { + return Status::NotSupported("NewAppendableFile", fname); +} + +SequentialFile::~SequentialFile() {} + +RandomAccessFile::~RandomAccessFile() {} + +WritableFile::~WritableFile() {} + +Logger::~Logger() {} + +FileLock::~FileLock() {} + +void Log(Logger* info_log, const char* format, ...) { + if (info_log != nullptr) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +static Status DoWriteStringToFile(Env* env, const Slice& data, + const std::string& fname, bool should_sync) { + WritableFile* file; + Status s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + s = file->Append(data); + if (s.ok() && should_sync) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; // Will auto-close if we did not close above + if (!s.ok()) { + env->DeleteFile(fname); + } + return s; +} + +Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, false); +} + +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, true); +} + +Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { + data->clear(); + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + static const int kBufferSize = 8192; + char* space = new char[kBufferSize]; + while (true) { + Slice fragment; + s = file->Read(kBufferSize, &fragment, space); + if (!s.ok()) { + break; + } + data->append(fragment.data(), fragment.size()); + if (fragment.empty()) { + break; + } + } + delete[] space; + delete file; + return s; +} + +EnvWrapper::~EnvWrapper() {} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/env_posix.cc b/MyExperiences copy/Pods/leveldb-library/util/env_posix.cc new file mode 100644 index 00000000..8c74f5ab --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/env_posix.cc @@ -0,0 +1,876 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/env_posix_test_helper.h" +#include "util/posix_logger.h" + +namespace leveldb { + +namespace { + +// Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles(). +int g_open_read_only_file_limit = -1; + +// Up to 1000 mmap regions for 64-bit binaries; none for 32-bit. +constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0; + +// Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit. +int g_mmap_limit = kDefaultMmapLimit; + +constexpr const size_t kWritableFileBufferSize = 65536; + +Status PosixError(const std::string& context, int error_number) { + if (error_number == ENOENT) { + return Status::NotFound(context, std::strerror(error_number)); + } else { + return Status::IOError(context, std::strerror(error_number)); + } +} + +// Helper class to limit resource usage to avoid exhaustion. +// Currently used to limit read-only file descriptors and mmap file usage +// so that we do not run out of file descriptors or virtual memory, or run into +// kernel performance problems for very large databases. +class Limiter { + public: + // Limit maximum number of resources to |max_acquires|. + Limiter(int max_acquires) : acquires_allowed_(max_acquires) {} + + Limiter(const Limiter&) = delete; + Limiter operator=(const Limiter&) = delete; + + // If another resource is available, acquire it and return true. + // Else return false. + bool Acquire() { + int old_acquires_allowed = + acquires_allowed_.fetch_sub(1, std::memory_order_relaxed); + + if (old_acquires_allowed > 0) return true; + + acquires_allowed_.fetch_add(1, std::memory_order_relaxed); + return false; + } + + // Release a resource acquired by a previous call to Acquire() that returned + // true. + void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); } + + private: + // The number of available resources. + // + // This is a counter and is not tied to the invariants of any other class, so + // it can be operated on safely using std::memory_order_relaxed. + std::atomic acquires_allowed_; +}; + +// Implements sequential read access in a file using read(). +// +// Instances of this class are thread-friendly but not thread-safe, as required +// by the SequentialFile API. +class PosixSequentialFile final : public SequentialFile { + public: + PosixSequentialFile(std::string filename, int fd) + : fd_(fd), filename_(filename) {} + ~PosixSequentialFile() override { close(fd_); } + + Status Read(size_t n, Slice* result, char* scratch) override { + Status status; + while (true) { + ::ssize_t read_size = ::read(fd_, scratch, n); + if (read_size < 0) { // Read error. + if (errno == EINTR) { + continue; // Retry + } + status = PosixError(filename_, errno); + break; + } + *result = Slice(scratch, read_size); + break; + } + return status; + } + + Status Skip(uint64_t n) override { + if (::lseek(fd_, n, SEEK_CUR) == static_cast(-1)) { + return PosixError(filename_, errno); + } + return Status::OK(); + } + + private: + const int fd_; + const std::string filename_; +}; + +// Implements random read access in a file using pread(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixRandomAccessFile final : public RandomAccessFile { + public: + // The new instance takes ownership of |fd|. |fd_limiter| must outlive this + // instance, and will be used to determine if . + PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter) + : has_permanent_fd_(fd_limiter->Acquire()), + fd_(has_permanent_fd_ ? fd : -1), + fd_limiter_(fd_limiter), + filename_(std::move(filename)) { + if (!has_permanent_fd_) { + assert(fd_ == -1); + ::close(fd); // The file will be opened on every read. + } + } + + ~PosixRandomAccessFile() override { + if (has_permanent_fd_) { + assert(fd_ != -1); + ::close(fd_); + fd_limiter_->Release(); + } + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + int fd = fd_; + if (!has_permanent_fd_) { + fd = ::open(filename_.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename_, errno); + } + } + + assert(fd != -1); + + Status status; + ssize_t read_size = ::pread(fd, scratch, n, static_cast(offset)); + *result = Slice(scratch, (read_size < 0) ? 0 : read_size); + if (read_size < 0) { + // An error: return a non-ok status. + status = PosixError(filename_, errno); + } + if (!has_permanent_fd_) { + // Close the temporary file descriptor opened earlier. + assert(fd != fd_); + ::close(fd); + } + return status; + } + + private: + const bool has_permanent_fd_; // If false, the file is opened on every read. + const int fd_; // -1 if has_permanent_fd_ is false. + Limiter* const fd_limiter_; + const std::string filename_; +}; + +// Implements random read access in a file using mmap(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixMmapReadableFile final : public RandomAccessFile { + public: + // mmap_base[0, length-1] points to the memory-mapped contents of the file. It + // must be the result of a successful call to mmap(). This instances takes + // over the ownership of the region. + // + // |mmap_limiter| must outlive this instance. The caller must have already + // aquired the right to use one mmap region, which will be released when this + // instance is destroyed. + PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length, + Limiter* mmap_limiter) + : mmap_base_(mmap_base), + length_(length), + mmap_limiter_(mmap_limiter), + filename_(std::move(filename)) {} + + ~PosixMmapReadableFile() override { + ::munmap(static_cast(mmap_base_), length_); + mmap_limiter_->Release(); + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + if (offset + n > length_) { + *result = Slice(); + return PosixError(filename_, EINVAL); + } + + *result = Slice(mmap_base_ + offset, n); + return Status::OK(); + } + + private: + char* const mmap_base_; + const size_t length_; + Limiter* const mmap_limiter_; + const std::string filename_; +}; + +class PosixWritableFile final : public WritableFile { + public: + PosixWritableFile(std::string filename, int fd) + : pos_(0), + fd_(fd), + is_manifest_(IsManifest(filename)), + filename_(std::move(filename)), + dirname_(Dirname(filename_)) {} + + ~PosixWritableFile() override { + if (fd_ >= 0) { + // Ignoring any potential errors + Close(); + } + } + + Status Append(const Slice& data) override { + size_t write_size = data.size(); + const char* write_data = data.data(); + + // Fit as much as possible into buffer. + size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_); + std::memcpy(buf_ + pos_, write_data, copy_size); + write_data += copy_size; + write_size -= copy_size; + pos_ += copy_size; + if (write_size == 0) { + return Status::OK(); + } + + // Can't fit in buffer, so need to do at least one write. + Status status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + // Small writes go to buffer, large writes are written directly. + if (write_size < kWritableFileBufferSize) { + std::memcpy(buf_, write_data, write_size); + pos_ = write_size; + return Status::OK(); + } + return WriteUnbuffered(write_data, write_size); + } + + Status Close() override { + Status status = FlushBuffer(); + const int close_result = ::close(fd_); + if (close_result < 0 && status.ok()) { + status = PosixError(filename_, errno); + } + fd_ = -1; + return status; + } + + Status Flush() override { return FlushBuffer(); } + + Status Sync() override { + // Ensure new files referred to by the manifest are in the filesystem. + // + // This needs to happen before the manifest file is flushed to disk, to + // avoid crashing in a state where the manifest refers to files that are not + // yet on disk. + Status status = SyncDirIfManifest(); + if (!status.ok()) { + return status; + } + + status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + return SyncFd(fd_, filename_); + } + + private: + Status FlushBuffer() { + Status status = WriteUnbuffered(buf_, pos_); + pos_ = 0; + return status; + } + + Status WriteUnbuffered(const char* data, size_t size) { + while (size > 0) { + ssize_t write_result = ::write(fd_, data, size); + if (write_result < 0) { + if (errno == EINTR) { + continue; // Retry + } + return PosixError(filename_, errno); + } + data += write_result; + size -= write_result; + } + return Status::OK(); + } + + Status SyncDirIfManifest() { + Status status; + if (!is_manifest_) { + return status; + } + + int fd = ::open(dirname_.c_str(), O_RDONLY); + if (fd < 0) { + status = PosixError(dirname_, errno); + } else { + status = SyncFd(fd, dirname_); + ::close(fd); + } + return status; + } + + // Ensures that all the caches associated with the given file descriptor's + // data are flushed all the way to durable media, and can withstand power + // failures. + // + // The path argument is only used to populate the description string in the + // returned Status if an error occurs. + static Status SyncFd(int fd, const std::string& fd_path) { +#if HAVE_FULLFSYNC + // On macOS and iOS, fsync() doesn't guarantee durability past power + // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some + // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to + // fsync(). + if (::fcntl(fd, F_FULLFSYNC) == 0) { + return Status::OK(); + } +#endif // HAVE_FULLFSYNC + +#if HAVE_FDATASYNC + bool sync_success = ::fdatasync(fd) == 0; +#else + bool sync_success = ::fsync(fd) == 0; +#endif // HAVE_FDATASYNC + + if (sync_success) { + return Status::OK(); + } + return PosixError(fd_path, errno); + } + + // Returns the directory name in a path pointing to a file. + // + // Returns "." if the path does not contain any directory separator. + static std::string Dirname(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return std::string("."); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return filename.substr(0, separator_pos); + } + + // Extracts the file name from a path pointing to a file. + // + // The returned Slice points to |filename|'s data buffer, so it is only valid + // while |filename| is alive and unchanged. + static Slice Basename(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return Slice(filename); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return Slice(filename.data() + separator_pos + 1, + filename.length() - separator_pos - 1); + } + + // True if the given file is a manifest file. + static bool IsManifest(const std::string& filename) { + return Basename(filename).starts_with("MANIFEST"); + } + + // buf_[0, pos_ - 1] contains data to be written to fd_. + char buf_[kWritableFileBufferSize]; + size_t pos_; + int fd_; + + const bool is_manifest_; // True if the file's name starts with MANIFEST. + const std::string filename_; + const std::string dirname_; // The directory of filename_. +}; + +int LockOrUnlock(int fd, bool lock) { + errno = 0; + struct ::flock file_lock_info; + std::memset(&file_lock_info, 0, sizeof(file_lock_info)); + file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK); + file_lock_info.l_whence = SEEK_SET; + file_lock_info.l_start = 0; + file_lock_info.l_len = 0; // Lock/unlock entire file. + return ::fcntl(fd, F_SETLK, &file_lock_info); +} + +// Instances are thread-safe because they are immutable. +class PosixFileLock : public FileLock { + public: + PosixFileLock(int fd, std::string filename) + : fd_(fd), filename_(std::move(filename)) {} + + int fd() const { return fd_; } + const std::string& filename() const { return filename_; } + + private: + const int fd_; + const std::string filename_; +}; + +// Tracks the files locked by PosixEnv::LockFile(). +// +// We maintain a separate set instead of relying on fcntrl(F_SETLK) because +// fcntl(F_SETLK) does not provide any protection against multiple uses from the +// same process. +// +// Instances are thread-safe because all member data is guarded by a mutex. +class PosixLockTable { + public: + bool Insert(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + bool succeeded = locked_files_.insert(fname).second; + mu_.Unlock(); + return succeeded; + } + void Remove(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + locked_files_.erase(fname); + mu_.Unlock(); + } + + private: + port::Mutex mu_; + std::set locked_files_ GUARDED_BY(mu_); +}; + +class PosixEnv : public Env { + public: + PosixEnv(); + ~PosixEnv() override { + static char msg[] = "PosixEnv singleton destroyed. Unsupported behavior!\n"; + std::fwrite(msg, 1, sizeof(msg), stderr); + std::abort(); + } + + Status NewSequentialFile(const std::string& filename, + SequentialFile** result) override { + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixSequentialFile(filename, fd); + return Status::OK(); + } + + Status NewRandomAccessFile(const std::string& filename, + RandomAccessFile** result) override { + *result = nullptr; + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!mmap_limiter_.Acquire()) { + *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_); + return Status::OK(); + } + + uint64_t file_size; + Status status = GetFileSize(filename, &file_size); + if (status.ok()) { + void* mmap_base = + ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); + if (mmap_base != MAP_FAILED) { + *result = new PosixMmapReadableFile(filename, + reinterpret_cast(mmap_base), + file_size, &mmap_limiter_); + } else { + status = PosixError(filename, errno); + } + } + ::close(fd); + if (!status.ok()) { + mmap_limiter_.Release(); + } + return status; + } + + Status NewWritableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_TRUNC | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + Status NewAppendableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + bool FileExists(const std::string& filename) override { + return ::access(filename.c_str(), F_OK) == 0; + } + + Status GetChildren(const std::string& directory_path, + std::vector* result) override { + result->clear(); + ::DIR* dir = ::opendir(directory_path.c_str()); + if (dir == nullptr) { + return PosixError(directory_path, errno); + } + struct ::dirent* entry; + while ((entry = ::readdir(dir)) != nullptr) { + result->emplace_back(entry->d_name); + } + ::closedir(dir); + return Status::OK(); + } + + Status DeleteFile(const std::string& filename) override { + if (::unlink(filename.c_str()) != 0) { + return PosixError(filename, errno); + } + return Status::OK(); + } + + Status CreateDir(const std::string& dirname) override { + if (::mkdir(dirname.c_str(), 0755) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status DeleteDir(const std::string& dirname) override { + if (::rmdir(dirname.c_str()) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status GetFileSize(const std::string& filename, uint64_t* size) override { + struct ::stat file_stat; + if (::stat(filename.c_str(), &file_stat) != 0) { + *size = 0; + return PosixError(filename, errno); + } + *size = file_stat.st_size; + return Status::OK(); + } + + Status RenameFile(const std::string& from, const std::string& to) override { + if (std::rename(from.c_str(), to.c_str()) != 0) { + return PosixError(from, errno); + } + return Status::OK(); + } + + Status LockFile(const std::string& filename, FileLock** lock) override { + *lock = nullptr; + + int fd = ::open(filename.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!locks_.Insert(filename)) { + ::close(fd); + return Status::IOError("lock " + filename, "already held by process"); + } + + if (LockOrUnlock(fd, true) == -1) { + int lock_errno = errno; + ::close(fd); + locks_.Remove(filename); + return PosixError("lock " + filename, lock_errno); + } + + *lock = new PosixFileLock(fd, filename); + return Status::OK(); + } + + Status UnlockFile(FileLock* lock) override { + PosixFileLock* posix_file_lock = static_cast(lock); + if (LockOrUnlock(posix_file_lock->fd(), false) == -1) { + return PosixError("unlock " + posix_file_lock->filename(), errno); + } + locks_.Remove(posix_file_lock->filename()); + ::close(posix_file_lock->fd()); + delete posix_file_lock; + return Status::OK(); + } + + void Schedule(void (*background_work_function)(void* background_work_arg), + void* background_work_arg) override; + + void StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) override; + + Status GetTestDirectory(std::string* result) override { + const char* env = std::getenv("TEST_TMPDIR"); + if (env && env[0] != '\0') { + *result = env; + } else { + char buf[100]; + std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", + static_cast(::geteuid())); + *result = buf; + } + + // The CreateDir status is ignored because the directory may already exist. + CreateDir(*result); + + return Status::OK(); + } + + Status NewLogger(const std::string& filename, Logger** result) override { + std::FILE* fp = std::fopen(filename.c_str(), "w"); + if (fp == nullptr) { + *result = nullptr; + return PosixError(filename, errno); + } else { + *result = new PosixLogger(fp); + return Status::OK(); + } + } + + uint64_t NowMicros() override { + static constexpr uint64_t kUsecondsPerSecond = 1000000; + struct ::timeval tv; + ::gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec; + } + + void SleepForMicroseconds(int micros) override { ::usleep(micros); } + + private: + void BackgroundThreadMain(); + + static void BackgroundThreadEntryPoint(PosixEnv* env) { + env->BackgroundThreadMain(); + } + + // Stores the work item data in a Schedule() call. + // + // Instances are constructed on the thread calling Schedule() and used on the + // background thread. + // + // This structure is thread-safe beacuse it is immutable. + struct BackgroundWorkItem { + explicit BackgroundWorkItem(void (*function)(void* arg), void* arg) + : function(function), arg(arg) {} + + void (*const function)(void*); + void* const arg; + }; + + port::Mutex background_work_mutex_; + port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_); + bool started_background_thread_ GUARDED_BY(background_work_mutex_); + + std::queue background_work_queue_ + GUARDED_BY(background_work_mutex_); + + PosixLockTable locks_; // Thread-safe. + Limiter mmap_limiter_; // Thread-safe. + Limiter fd_limiter_; // Thread-safe. +}; + +// Return the maximum number of concurrent mmaps. +int MaxMmaps() { return g_mmap_limit; } + +// Return the maximum number of read-only files to keep open. +int MaxOpenFiles() { + if (g_open_read_only_file_limit >= 0) { + return g_open_read_only_file_limit; + } + struct ::rlimit rlim; + if (::getrlimit(RLIMIT_NOFILE, &rlim)) { + // getrlimit failed, fallback to hard-coded default. + g_open_read_only_file_limit = 50; + } else if (rlim.rlim_cur == RLIM_INFINITY) { + g_open_read_only_file_limit = std::numeric_limits::max(); + } else { + // Allow use of 20% of available file descriptors for read-only files. + g_open_read_only_file_limit = rlim.rlim_cur / 5; + } + return g_open_read_only_file_limit; +} + +} // namespace + +PosixEnv::PosixEnv() + : background_work_cv_(&background_work_mutex_), + started_background_thread_(false), + mmap_limiter_(MaxMmaps()), + fd_limiter_(MaxOpenFiles()) {} + +void PosixEnv::Schedule( + void (*background_work_function)(void* background_work_arg), + void* background_work_arg) { + background_work_mutex_.Lock(); + + // Start the background thread, if we haven't done so already. + if (!started_background_thread_) { + started_background_thread_ = true; + std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this); + background_thread.detach(); + } + + // If the queue is empty, the background thread may be waiting for work. + if (background_work_queue_.empty()) { + background_work_cv_.Signal(); + } + + background_work_queue_.emplace(background_work_function, background_work_arg); + background_work_mutex_.Unlock(); +} + +void PosixEnv::BackgroundThreadMain() { + while (true) { + background_work_mutex_.Lock(); + + // Wait until there is work to be done. + while (background_work_queue_.empty()) { + background_work_cv_.Wait(); + } + + assert(!background_work_queue_.empty()); + auto background_work_function = background_work_queue_.front().function; + void* background_work_arg = background_work_queue_.front().arg; + background_work_queue_.pop(); + + background_work_mutex_.Unlock(); + background_work_function(background_work_arg); + } +} + +namespace { + +// Wraps an Env instance whose destructor is never created. +// +// Intended usage: +// using PlatformSingletonEnv = SingletonEnv; +// void ConfigurePosixEnv(int param) { +// PlatformSingletonEnv::AssertEnvNotInitialized(); +// // set global configuration flags. +// } +// Env* Env::Default() { +// static PlatformSingletonEnv default_env; +// return default_env.env(); +// } +template +class SingletonEnv { + public: + SingletonEnv() { +#if !defined(NDEBUG) + env_initialized_.store(true, std::memory_order::memory_order_relaxed); +#endif // !defined(NDEBUG) + static_assert(sizeof(env_storage_) >= sizeof(EnvType), + "env_storage_ will not fit the Env"); + static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType), + "env_storage_ does not meet the Env's alignment needs"); + new (&env_storage_) EnvType(); + } + ~SingletonEnv() = default; + + SingletonEnv(const SingletonEnv&) = delete; + SingletonEnv& operator=(const SingletonEnv&) = delete; + + Env* env() { return reinterpret_cast(&env_storage_); } + + static void AssertEnvNotInitialized() { +#if !defined(NDEBUG) + assert(!env_initialized_.load(std::memory_order::memory_order_relaxed)); +#endif // !defined(NDEBUG) + } + + private: + typename std::aligned_storage::type + env_storage_; +#if !defined(NDEBUG) + static std::atomic env_initialized_; +#endif // !defined(NDEBUG) +}; + +#if !defined(NDEBUG) +template +std::atomic SingletonEnv::env_initialized_; +#endif // !defined(NDEBUG) + +using PosixDefaultEnv = SingletonEnv; + +} // namespace + +void PosixEnv::StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) { + std::thread new_thread(thread_main, thread_main_arg); + new_thread.detach(); +} + +void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_open_read_only_file_limit = limit; +} + +void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_mmap_limit = limit; +} + +Env* Env::Default() { + static PosixDefaultEnv env_container; + return env_container.env(); +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/env_posix_test_helper.h b/MyExperiences copy/Pods/leveldb-library/util/env_posix_test_helper.h new file mode 100644 index 00000000..03869605 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/env_posix_test_helper.h @@ -0,0 +1,28 @@ +// Copyright 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ + +namespace leveldb { + +class EnvPosixTest; + +// A helper for the POSIX Env to facilitate testing. +class EnvPosixTestHelper { + private: + friend class EnvPosixTest; + + // Set the maximum number of read-only files that will be opened. + // Must be called before creating an Env. + static void SetReadOnlyFDLimit(int limit); + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/env_windows_test_helper.h b/MyExperiences copy/Pods/leveldb-library/util/env_windows_test_helper.h new file mode 100644 index 00000000..e6f60205 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/env_windows_test_helper.h @@ -0,0 +1,25 @@ +// Copyright 2018 (c) The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ + +namespace leveldb { + +class EnvWindowsTest; + +// A helper for the Windows Env to facilitate testing. +class EnvWindowsTestHelper { + private: + friend class CorruptionTest; + friend class EnvWindowsTest; + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/filter_policy.cc b/MyExperiences copy/Pods/leveldb-library/util/filter_policy.cc new file mode 100644 index 00000000..90fd754d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/filter_policy.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +namespace leveldb { + +FilterPolicy::~FilterPolicy() {} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/hash.cc b/MyExperiences copy/Pods/leveldb-library/util/hash.cc new file mode 100644 index 00000000..67dc134e --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/hash.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/hash.h" + +#include + +#include "util/coding.h" + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels. The real definition should be provided externally. +// This one is a fallback version for unsupported compilers. +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed) { + // Similar to murmur hash + const uint32_t m = 0xc6a4a793; + const uint32_t r = 24; + const char* limit = data + n; + uint32_t h = seed ^ (n * m); + + // Pick up four bytes at a time + while (data + 4 <= limit) { + uint32_t w = DecodeFixed32(data); + data += 4; + h += w; + h *= m; + h ^= (h >> 16); + } + + // Pick up remaining bytes + switch (limit - data) { + case 3: + h += static_cast(data[2]) << 16; + FALLTHROUGH_INTENDED; + case 2: + h += static_cast(data[1]) << 8; + FALLTHROUGH_INTENDED; + case 1: + h += static_cast(data[0]); + h *= m; + h ^= (h >> r); + break; + } + return h; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/hash.h b/MyExperiences copy/Pods/leveldb-library/util/hash.h new file mode 100644 index 00000000..74bdb6e7 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/hash.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Simple hash function used for internal data structures + +#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ +#define STORAGE_LEVELDB_UTIL_HASH_H_ + +#include +#include + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/histogram.cc b/MyExperiences copy/Pods/leveldb-library/util/histogram.cc new file mode 100644 index 00000000..65092c88 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/histogram.cc @@ -0,0 +1,272 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/histogram.h" + +#include +#include + +#include "port/port.h" + +namespace leveldb { + +const double Histogram::kBucketLimit[kNumBuckets] = { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 12, + 14, + 16, + 18, + 20, + 25, + 30, + 35, + 40, + 45, + 50, + 60, + 70, + 80, + 90, + 100, + 120, + 140, + 160, + 180, + 200, + 250, + 300, + 350, + 400, + 450, + 500, + 600, + 700, + 800, + 900, + 1000, + 1200, + 1400, + 1600, + 1800, + 2000, + 2500, + 3000, + 3500, + 4000, + 4500, + 5000, + 6000, + 7000, + 8000, + 9000, + 10000, + 12000, + 14000, + 16000, + 18000, + 20000, + 25000, + 30000, + 35000, + 40000, + 45000, + 50000, + 60000, + 70000, + 80000, + 90000, + 100000, + 120000, + 140000, + 160000, + 180000, + 200000, + 250000, + 300000, + 350000, + 400000, + 450000, + 500000, + 600000, + 700000, + 800000, + 900000, + 1000000, + 1200000, + 1400000, + 1600000, + 1800000, + 2000000, + 2500000, + 3000000, + 3500000, + 4000000, + 4500000, + 5000000, + 6000000, + 7000000, + 8000000, + 9000000, + 10000000, + 12000000, + 14000000, + 16000000, + 18000000, + 20000000, + 25000000, + 30000000, + 35000000, + 40000000, + 45000000, + 50000000, + 60000000, + 70000000, + 80000000, + 90000000, + 100000000, + 120000000, + 140000000, + 160000000, + 180000000, + 200000000, + 250000000, + 300000000, + 350000000, + 400000000, + 450000000, + 500000000, + 600000000, + 700000000, + 800000000, + 900000000, + 1000000000, + 1200000000, + 1400000000, + 1600000000, + 1800000000, + 2000000000, + 2500000000.0, + 3000000000.0, + 3500000000.0, + 4000000000.0, + 4500000000.0, + 5000000000.0, + 6000000000.0, + 7000000000.0, + 8000000000.0, + 9000000000.0, + 1e200, +}; + +void Histogram::Clear() { + min_ = kBucketLimit[kNumBuckets - 1]; + max_ = 0; + num_ = 0; + sum_ = 0; + sum_squares_ = 0; + for (int i = 0; i < kNumBuckets; i++) { + buckets_[i] = 0; + } +} + +void Histogram::Add(double value) { + // Linear search is fast enough for our usage in db_bench + int b = 0; + while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) { + b++; + } + buckets_[b] += 1.0; + if (min_ > value) min_ = value; + if (max_ < value) max_ = value; + num_++; + sum_ += value; + sum_squares_ += (value * value); +} + +void Histogram::Merge(const Histogram& other) { + if (other.min_ < min_) min_ = other.min_; + if (other.max_ > max_) max_ = other.max_; + num_ += other.num_; + sum_ += other.sum_; + sum_squares_ += other.sum_squares_; + for (int b = 0; b < kNumBuckets; b++) { + buckets_[b] += other.buckets_[b]; + } +} + +double Histogram::Median() const { return Percentile(50.0); } + +double Histogram::Percentile(double p) const { + double threshold = num_ * (p / 100.0); + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + sum += buckets_[b]; + if (sum >= threshold) { + // Scale linearly within this bucket + double left_point = (b == 0) ? 0 : kBucketLimit[b - 1]; + double right_point = kBucketLimit[b]; + double left_sum = sum - buckets_[b]; + double right_sum = sum; + double pos = (threshold - left_sum) / (right_sum - left_sum); + double r = left_point + (right_point - left_point) * pos; + if (r < min_) r = min_; + if (r > max_) r = max_; + return r; + } + } + return max_; +} + +double Histogram::Average() const { + if (num_ == 0.0) return 0; + return sum_ / num_; +} + +double Histogram::StandardDeviation() const { + if (num_ == 0.0) return 0; + double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); + return sqrt(variance); +} + +std::string Histogram::ToString() const { + std::string r; + char buf[200]; + snprintf(buf, sizeof(buf), "Count: %.0f Average: %.4f StdDev: %.2f\n", num_, + Average(), StandardDeviation()); + r.append(buf); + snprintf(buf, sizeof(buf), "Min: %.4f Median: %.4f Max: %.4f\n", + (num_ == 0.0 ? 0.0 : min_), Median(), max_); + r.append(buf); + r.append("------------------------------------------------------\n"); + const double mult = 100.0 / num_; + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + if (buckets_[b] <= 0.0) continue; + sum += buckets_[b]; + snprintf(buf, sizeof(buf), "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ", + ((b == 0) ? 0.0 : kBucketLimit[b - 1]), // left + kBucketLimit[b], // right + buckets_[b], // count + mult * buckets_[b], // percentage + mult * sum); // cumulative percentage + r.append(buf); + + // Add hash marks based on percentage; 20 marks for 100%. + int marks = static_cast(20 * (buckets_[b] / num_) + 0.5); + r.append(marks, '#'); + r.push_back('\n'); + } + return r; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/histogram.h b/MyExperiences copy/Pods/leveldb-library/util/histogram.h new file mode 100644 index 00000000..4da60fba --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/histogram.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ +#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ + +#include + +namespace leveldb { + +class Histogram { + public: + Histogram() {} + ~Histogram() {} + + void Clear(); + void Add(double value); + void Merge(const Histogram& other); + + std::string ToString() const; + + private: + enum { kNumBuckets = 154 }; + + double Median() const; + double Percentile(double p) const; + double Average() const; + double StandardDeviation() const; + + static const double kBucketLimit[kNumBuckets]; + + double min_; + double max_; + double num_; + double sum_; + double sum_squares_; + + double buckets_[kNumBuckets]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/logging.cc b/MyExperiences copy/Pods/leveldb-library/util/logging.cc new file mode 100644 index 00000000..1ad8f1c7 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/logging.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/logging.h" + +#include +#include +#include +#include + +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" + +namespace leveldb { + +void AppendNumberTo(std::string* str, uint64_t num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); + str->append(buf); +} + +void AppendEscapedStringTo(std::string* str, const Slice& value) { + for (size_t i = 0; i < value.size(); i++) { + char c = value[i]; + if (c >= ' ' && c <= '~') { + str->push_back(c); + } else { + char buf[10]; + snprintf(buf, sizeof(buf), "\\x%02x", + static_cast(c) & 0xff); + str->append(buf); + } + } +} + +std::string NumberToString(uint64_t num) { + std::string r; + AppendNumberTo(&r, num); + return r; +} + +std::string EscapeString(const Slice& value) { + std::string r; + AppendEscapedStringTo(&r, value); + return r; +} + +bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { + // Constants that will be optimized away. + constexpr const uint64_t kMaxUint64 = std::numeric_limits::max(); + constexpr const char kLastDigitOfMaxUint64 = + '0' + static_cast(kMaxUint64 % 10); + + uint64_t value = 0; + + // reinterpret_cast-ing from char* to unsigned char* to avoid signedness. + const unsigned char* start = + reinterpret_cast(in->data()); + + const unsigned char* end = start + in->size(); + const unsigned char* current = start; + for (; current != end; ++current) { + const unsigned char ch = *current; + if (ch < '0' || ch > '9') break; + + // Overflow check. + // kMaxUint64 / 10 is also constant and will be optimized away. + if (value > kMaxUint64 / 10 || + (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) { + return false; + } + + value = (value * 10) + (ch - '0'); + } + + *val = value; + const size_t digits_consumed = current - start; + in->remove_prefix(digits_consumed); + return digits_consumed != 0; +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/logging.h b/MyExperiences copy/Pods/leveldb-library/util/logging.h new file mode 100644 index 00000000..8ff2da86 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/logging.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Must not be included from any .h files to avoid polluting the namespace +// with macros. + +#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ +#define STORAGE_LEVELDB_UTIL_LOGGING_H_ + +#include +#include + +#include + +#include "port/port.h" + +namespace leveldb { + +class Slice; +class WritableFile; + +// Append a human-readable printout of "num" to *str +void AppendNumberTo(std::string* str, uint64_t num); + +// Append a human-readable printout of "value" to *str. +// Escapes any non-printable characters found in "value". +void AppendEscapedStringTo(std::string* str, const Slice& value); + +// Return a human-readable printout of "num" +std::string NumberToString(uint64_t num); + +// Return a human-readable version of "value". +// Escapes any non-printable characters found in "value". +std::string EscapeString(const Slice& value); + +// Parse a human-readable number from "*in" into *value. On success, +// advances "*in" past the consumed number and sets "*val" to the +// numeric value. Otherwise, returns false and leaves *in in an +// unspecified state. +bool ConsumeDecimalNumber(Slice* in, uint64_t* val); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/mutexlock.h b/MyExperiences copy/Pods/leveldb-library/util/mutexlock.h new file mode 100644 index 00000000..0cb2e250 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/mutexlock.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ +#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ + +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +// Helper class that locks a mutex on construction and unlocks the mutex when +// the destructor of the MutexLock object is invoked. +// +// Typical usage: +// +// void MyClass::MyMethod() { +// MutexLock l(&mu_); // mu_ is an instance variable +// ... some complex code, possibly with multiple return paths ... +// } + +class SCOPED_LOCKABLE MutexLock { + public: + explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + port::Mutex* const mu_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/no_destructor.h b/MyExperiences copy/Pods/leveldb-library/util/no_destructor.h new file mode 100644 index 00000000..a0d3b870 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/no_destructor.h @@ -0,0 +1,46 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ +#define STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ + +#include +#include + +namespace leveldb { + +// Wraps an instance whose destructor is never called. +// +// This is intended for use with function-level static variables. +template +class NoDestructor { + public: + template + explicit NoDestructor(ConstructorArgTypes&&... constructor_args) { + static_assert(sizeof(instance_storage_) >= sizeof(InstanceType), + "instance_storage_ is not large enough to hold the instance"); + static_assert( + alignof(decltype(instance_storage_)) >= alignof(InstanceType), + "instance_storage_ does not meet the instance's alignment requirement"); + new (&instance_storage_) + InstanceType(std::forward(constructor_args)...); + } + + ~NoDestructor() = default; + + NoDestructor(const NoDestructor&) = delete; + NoDestructor& operator=(const NoDestructor&) = delete; + + InstanceType* get() { + return reinterpret_cast(&instance_storage_); + } + + private: + typename std::aligned_storage::type instance_storage_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/options.cc b/MyExperiences copy/Pods/leveldb-library/util/options.cc new file mode 100644 index 00000000..62de5bf0 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/options.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/options.h" + +#include "leveldb/comparator.h" +#include "leveldb/env.h" + +namespace leveldb { + +Options::Options() : comparator(BytewiseComparator()), env(Env::Default()) {} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/posix_logger.h b/MyExperiences copy/Pods/leveldb-library/util/posix_logger.h new file mode 100644 index 00000000..28e15d10 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/posix_logger.h @@ -0,0 +1,130 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class PosixLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~PosixLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + struct ::timeval now_timeval; + ::gettimeofday(&now_timeval, nullptr); + const std::time_t now_seconds = now_timeval.tv_sec; + struct std::tm now_components; + ::localtime_r(&now_seconds, &now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.tm_year + 1900, now_components.tm_mon + 1, + now_components.tm_mday, now_components.tm_hour, now_components.tm_min, + now_components.tm_sec, static_cast(now_timeval.tv_usec), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/random.h b/MyExperiences copy/Pods/leveldb-library/util/random.h new file mode 100644 index 00000000..76f7daf5 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/random.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ +#define STORAGE_LEVELDB_UTIL_RANDOM_H_ + +#include + +namespace leveldb { + +// A very simple random number generator. Not especially good at +// generating truly random bits, but good enough for our needs in this +// package. +class Random { + private: + uint32_t seed_; + + public: + explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { + // Avoid bad seeds. + if (seed_ == 0 || seed_ == 2147483647L) { + seed_ = 1; + } + } + uint32_t Next() { + static const uint32_t M = 2147483647L; // 2^31-1 + static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64_t product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = static_cast((product >> 31) + (product & M)); + // The first reduction may overflow by 1 bit, so we may need to + // repeat. mod == M is not possible; using > allows the faster + // sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; + } + // Returns a uniformly distributed value in the range [0..n-1] + // REQUIRES: n > 0 + uint32_t Uniform(int n) { return Next() % n; } + + // Randomly returns true ~"1/n" of the time, and false otherwise. + // REQUIRES: n > 0 + bool OneIn(int n) { return (Next() % n) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with exponential bias towards smaller numbers. + uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/status.cc b/MyExperiences copy/Pods/leveldb-library/util/status.cc new file mode 100644 index 00000000..6ca8da6d --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/status.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/status.h" + +#include + +#include "port/port.h" + +namespace leveldb { + +const char* Status::CopyState(const char* state) { + uint32_t size; + memcpy(&size, state, sizeof(size)); + char* result = new char[size + 5]; + memcpy(result, state, size + 5); + return result; +} + +Status::Status(Code code, const Slice& msg, const Slice& msg2) { + assert(code != kOk); + const uint32_t len1 = msg.size(); + const uint32_t len2 = msg2.size(); + const uint32_t size = len1 + (len2 ? (2 + len2) : 0); + char* result = new char[size + 5]; + memcpy(result, &size, sizeof(size)); + result[4] = static_cast(code); + memcpy(result + 5, msg.data(), len1); + if (len2) { + result[5 + len1] = ':'; + result[6 + len1] = ' '; + memcpy(result + 7 + len1, msg2.data(), len2); + } + state_ = result; +} + +std::string Status::ToString() const { + if (state_ == nullptr) { + return "OK"; + } else { + char tmp[30]; + const char* type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kNotFound: + type = "NotFound: "; + break; + case kCorruption: + type = "Corruption: "; + break; + case kNotSupported: + type = "Not implemented: "; + break; + case kInvalidArgument: + type = "Invalid argument: "; + break; + case kIOError: + type = "IO error: "; + break; + default: + snprintf(tmp, sizeof(tmp), + "Unknown code(%d): ", static_cast(code())); + type = tmp; + break; + } + std::string result(type); + uint32_t length; + memcpy(&length, state_, sizeof(length)); + result.append(state_ + 5, length); + return result; + } +} + +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/testharness.cc b/MyExperiences copy/Pods/leveldb-library/util/testharness.cc new file mode 100644 index 00000000..318ecfa3 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/testharness.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testharness.h" + +#include +#include +#include + +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { +namespace test { + +namespace { +struct Test { + const char* base; + const char* name; + void (*func)(); +}; +std::vector* tests; +} // namespace + +bool RegisterTest(const char* base, const char* name, void (*func)()) { + if (tests == nullptr) { + tests = new std::vector; + } + Test t; + t.base = base; + t.name = name; + t.func = func; + tests->push_back(t); + return true; +} + +int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + + int num = 0; + if (tests != nullptr) { + for (size_t i = 0; i < tests->size(); i++) { + const Test& t = (*tests)[i]; + if (matcher != nullptr) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == nullptr) { + continue; + } + } + fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); + (*t.func)(); + ++num; + } + } + fprintf(stderr, "==== PASSED %d tests\n", num); + return 0; +} + +std::string TmpDir() { + std::string dir; + Status s = Env::Default()->GetTestDirectory(&dir); + ASSERT_TRUE(s.ok()) << s.ToString(); + return dir; +} + +int RandomSeed() { + const char* env = getenv("TEST_RANDOM_SEED"); + int result = (env != nullptr ? atoi(env) : 301); + if (result <= 0) { + result = 301; + } + return result; +} + +} // namespace test +} // namespace leveldb diff --git a/MyExperiences copy/Pods/leveldb-library/util/testharness.h b/MyExperiences copy/Pods/leveldb-library/util/testharness.h new file mode 100644 index 00000000..72cd1629 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/testharness.h @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ +#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ + +#include +#include + +#include + +#include "leveldb/status.h" + +namespace leveldb { +namespace test { + +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// +// Returns 0 if all tests pass. +// Dies or returns a non-zero value if some test fails. +int RunAllTests(); + +// Return the directory to use for temporary storage. +std::string TmpDir(); + +// Return a randomization seed for this run. Typically returns the +// same number on repeated invocations of this binary, but automated +// runs may be able to vary the seed. +int RandomSeed(); + +// An instance of Tester is allocated to hold temporary state during +// the execution of an assertion. +class Tester { + private: + bool ok_; + const char* fname_; + int line_; + std::stringstream ss_; + + public: + Tester(const char* f, int l) : ok_(true), fname_(f), line_(l) {} + + ~Tester() { + if (!ok_) { + fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); + exit(1); + } + } + + Tester& Is(bool b, const char* msg) { + if (!b) { + ss_ << " Assertion failure " << msg; + ok_ = false; + } + return *this; + } + + Tester& IsOk(const Status& s) { + if (!s.ok()) { + ss_ << " " << s.ToString(); + ok_ = false; + } + return *this; + } + +#define BINARY_OP(name, op) \ + template \ + Tester& name(const X& x, const Y& y) { \ + if (!(x op y)) { \ + ss_ << " failed: " << x << (" " #op " ") << y; \ + ok_ = false; \ + } \ + return *this; \ + } + + BINARY_OP(IsEq, ==) + BINARY_OP(IsNe, !=) + BINARY_OP(IsGe, >=) + BINARY_OP(IsGt, >) + BINARY_OP(IsLe, <=) + BINARY_OP(IsLt, <) +#undef BINARY_OP + + // Attach the specified value to the error message if an error has occurred + template + Tester& operator<<(const V& value) { + if (!ok_) { + ss_ << " " << value; + } + return *this; + } +}; + +#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) +#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) +#define ASSERT_EQ(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a), (b)) +#define ASSERT_NE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a), (b)) +#define ASSERT_GE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a), (b)) +#define ASSERT_GT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a), (b)) +#define ASSERT_LE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a), (b)) +#define ASSERT_LT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a), (b)) + +#define TCONCAT(a, b) TCONCAT1(a, b) +#define TCONCAT1(a, b) a##b + +#define TEST(base, name) \ + class TCONCAT(_Test_, name) : public base { \ + public: \ + void _Run(); \ + static void _RunIt() { \ + TCONCAT(_Test_, name) t; \ + t._Run(); \ + } \ + }; \ + bool TCONCAT(_Test_ignored_, name) = ::leveldb::test::RegisterTest( \ + #base, #name, &TCONCAT(_Test_, name)::_RunIt); \ + void TCONCAT(_Test_, name)::_Run() + +// Register the specified test. Typically not used directly, but +// invoked via the macro expansion of TEST. +bool RegisterTest(const char* base, const char* name, void (*func)()); + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/testutil.h b/MyExperiences copy/Pods/leveldb-library/util/testutil.h new file mode 100644 index 00000000..bb4051ba --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/testutil.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ +#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ + +#include "helpers/memenv/memenv.h" +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Store in *dst a random string of length "len" and return a Slice that +// references the generated data. +Slice RandomString(Random* rnd, int len, std::string* dst); + +// Return a random key with the specified length that may contain interesting +// characters (e.g. \x00, \xff, etc.). +std::string RandomKey(Random* rnd, int len); + +// Store in *dst a string of length "len" that will compress to +// "N*compressed_fraction" bytes and return a Slice that references +// the generated data. +Slice CompressibleString(Random* rnd, double compressed_fraction, size_t len, + std::string* dst); + +// A wrapper that allows injection of errors. +class ErrorEnv : public EnvWrapper { + public: + bool writable_file_error_; + int num_writable_file_errors_; + + ErrorEnv() + : EnvWrapper(NewMemEnv(Env::Default())), + writable_file_error_(false), + num_writable_file_errors_(0) {} + ~ErrorEnv() override { delete target(); } + + Status NewWritableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewWritableFile(fname, result); + } + + Status NewAppendableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewAppendableFile(fname, result); + } +}; + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/MyExperiences copy/Pods/leveldb-library/util/windows_logger.h b/MyExperiences copy/Pods/leveldb-library/util/windows_logger.h new file mode 100644 index 00000000..92960638 --- /dev/null +++ b/MyExperiences copy/Pods/leveldb-library/util/windows_logger.h @@ -0,0 +1,124 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation for the Windows platform. + +#ifndef STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class WindowsLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit WindowsLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~WindowsLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + SYSTEMTIME now_components; + ::GetLocalTime(&now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.wYear, now_components.wMonth, now_components.wDay, + now_components.wHour, now_components.wMinute, now_components.wSecond, + static_cast(now_components.wMilliseconds * 1000), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ diff --git a/MyExperiences copy/Pods/nanopb/LICENSE.txt b/MyExperiences copy/Pods/nanopb/LICENSE.txt new file mode 100644 index 00000000..d11c9af1 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/MyExperiences copy/Pods/nanopb/README.md b/MyExperiences copy/Pods/nanopb/README.md new file mode 100644 index 00000000..1a73cdda --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/README.md @@ -0,0 +1,71 @@ +Nanopb - Protocol Buffers for Embedded Systems +============================================== + +[![Build Status](https://travis-ci.org/nanopb/nanopb.svg?branch=master)](https://travis-ci.org/nanopb/nanopb) + +Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is +especially suitable for use in microcontrollers, but fits any memory +restricted system. + +* **Homepage:** https://jpa.kapsi.fi/nanopb/ +* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/ +* **Downloads:** https://jpa.kapsi.fi/nanopb/download/ +* **Forum:** https://groups.google.com/forum/#!forum/nanopb + + + +Using the nanopb library +------------------------ +To use the nanopb library, you need to do two things: + +1. Compile your .proto files for nanopb, using `protoc`. +2. Include *pb_encode.c*, *pb_decode.c* and *pb_common.c* in your project. + +The easiest way to get started is to study the project in "examples/simple". +It contains a Makefile, which should work directly under most Linux systems. +However, for any other kind of build system, see the manual steps in +README.txt in that folder. + + + +Using the Protocol Buffers compiler (protoc) +-------------------------------------------- +The nanopb generator is implemented as a plugin for the Google's own `protoc` +compiler. This has the advantage that there is no need to reimplement the +basic parsing of .proto files. However, it does mean that you need the +Google's protobuf library in order to run the generator. + +If you have downloaded a binary package for nanopb (either Windows, Linux or +Mac OS X version), the `protoc` binary is included in the 'generator-bin' +folder. In this case, you are ready to go. Simply run this command: + + generator-bin/protoc --nanopb_out=. myprotocol.proto + +However, if you are using a git checkout or a plain source distribution, you +need to provide your own version of `protoc` and the Google's protobuf library. +On Linux, the necessary packages are `protobuf-compiler` and `python-protobuf`. +On Windows, you can either build Google's protobuf library from source or use +one of the binary distributions of it. In either case, if you use a separate +`protoc`, you need to manually give the path to nanopb generator: + + protoc --plugin=protoc-gen-nanopb=nanopb/generator/protoc-gen-nanopb ... + + + +Running the tests +----------------- +If you want to perform further development of the nanopb core, or to verify +its functionality using your compiler and platform, you'll want to run the +test suite. The build rules for the test suite are implemented using Scons, +so you need to have that installed (ex: `sudo apt install scons` on Ubuntu). To run the tests: + + cd tests + scons + +This will show the progress of various test cases. If the output does not +end in an error, the test cases were successful. + +Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually +supporting the same command line options as gcc does. To run tests on +Mac OS X, use: "scons CC=clang CXX=clang". Same way can be used to run +tests with different compilers on any platform. diff --git a/MyExperiences copy/Pods/nanopb/pb.h b/MyExperiences copy/Pods/nanopb/pb.h new file mode 100644 index 00000000..2c5868b2 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb.h @@ -0,0 +1,599 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/* Don't encode scalar arrays as packed. This is only to be used when + * the decoder on the receiving side cannot process packed scalar arrays. + * Such example is older protobuf.js. */ +/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */ + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.3.9.5 + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#else +#define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_BOOL 0x00 /* bool */ +#define PB_LTYPE_VARINT 0x01 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x02 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x03 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x04 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x05 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x05 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x06 + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x07 + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x08 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x09 + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0A + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0B +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside an union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. + */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for repeated static fixed count fields.*/ +#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + 0, \ + pb_membersize(message, field[0]), \ + pb_arraysize(message, field), ptr} + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#endif diff --git a/MyExperiences copy/Pods/nanopb/pb_common.c b/MyExperiences copy/Pods/nanopb/pb_common.c new file mode 100644 index 00000000..4fb7186b --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_common.c @@ -0,0 +1,97 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + { + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos++; + + if (iter->pos->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } + else + { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && + iter->pos->data_offset == PB_SIZE_MAX) + { + /* Don't advance pointers inside unions */ + return true; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + { + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + { + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + { + /* Found the wanted field */ + return true; + } + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + + diff --git a/MyExperiences copy/Pods/nanopb/pb_common.h b/MyExperiences copy/Pods/nanopb/pb_common.h new file mode 100644 index 00000000..60b3d374 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_common.h @@ -0,0 +1,42 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/MyExperiences copy/Pods/nanopb/pb_decode.c b/MyExperiences copy/Pods/nanopb/pb_decode.c new file mode 100644 index 00000000..ce5c4ae9 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_decode.c @@ -0,0 +1,1548 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_bool, + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + if (count == 0) + return true; + +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) + { + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + (*size)++; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)iter->pSize; + char *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + + if ((*size)++ >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + +#ifdef __AVR__ + /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284 + * Realloc to size of 1 byte can cause corruption of the malloc structures. + */ + if (data_size == 1 && array_size == 1) + { + data_size = 2; + } +#endif + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(pItem, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + } + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = iter->pos->tag; + } + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + { + return func(stream, iter->pos, iter->pData); + } + else + { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, iter->pos, *(void**)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + size_t remain = (substream.bytes_left - 1) / iter->pos->data_size + 1; + if (remain < PB_SIZE_MAX - allocated_size) + allocated_size += remain; + else + allocated_size += 1; + + if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + if (!allocate_field(stream, iter->pData, iter->pos->data_size, (size_t)(*size + 1))) + return false; + + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + (*size)++; + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; +#ifdef PB_OLD_CALLBACK_STYLE + void *arg; +#else + void **arg; +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + +#ifdef PB_OLD_CALLBACK_STYLE + arg = pCallback->arg; +#else + arg = &(pCallback->arg); +#endif + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)iter->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)iter->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData); + } + else if (iter->pos->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + } + else + { + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + const pb_field_t *fixed_count_field = NULL; + pb_size_t fixed_count_size = 0; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED + && iter.pSize == iter.pData) + { + if (fixed_count_field != iter.pos) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.pos; + fixed_count_size = 0; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned req_field_count; + pb_type_t last_type; + unsigned i; + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_noinit(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && PB_ATYPE(type) != PB_ATYPE_CALLBACK) + { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + pItem = *(void**)iter->pData; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) { + /* No _count field so use size of the array */ + count = iter->pos->array_size; + } else { + count = *(pb_size_t*)iter->pSize; + } + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + { + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } + } + + if (pItem) + { + while (count--) + { + pb_release((const pb_field_t*)iter->pos->ptr, pItem); + pItem = (char*)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)iter->pSize = 0; + } + + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_bool(pb_istream_t *stream, bool *dest) +{ + return pb_dec_bool(stream, NULL, (void*)dest); +} + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} +#endif + +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t value; + PB_UNUSED(field); + if (!pb_decode_varint32(stream, &value)) + return false; + + *(bool*)dest = (value != 0); + return true; +} + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t*)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(dest, 0, field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)dest, field->data_size); +} diff --git a/MyExperiences copy/Pods/nanopb/pb_decode.h b/MyExperiences copy/Pods/nanopb/pb_decode.h new file mode 100644 index 00000000..3577c201 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_decode.h @@ -0,0 +1,178 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode a bool value in varint format. */ +bool pb_decode_bool(pb_istream_t *stream, bool *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/MyExperiences copy/Pods/nanopb/pb_encode.c b/MyExperiences copy/Pods/nanopb/pb_encode.c new file mode 100644 index 00000000..0f89d981 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_encode.c @@ -0,0 +1,902 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t + +static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_bool, + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (count > 0 && stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Read a bool value without causing undefined behavior even if the value + * is invalid. See issue #434 and + * https://stackoverflow.com/questions/27661768/weird-results-for-conditional + */ +static bool safe_read_bool(const void *pSize) +{ + const char *p = (const char *)pSize; + size_t i; + for (i = 0; i < sizeof(bool); i++) + { + if (p[i] != 0) + return true; + } + return false; +} + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; +#ifndef PB_ENCODE_ARRAYS_UNPACKED + size_t size; +#endif + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + +#ifndef PB_ENCODE_ARRAYS_UNPACKED + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + p = pData; + for (i = 0; i < count; i++) + { + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) + { + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + } + else +#endif + { + p = pData; + for (i = 0; i < count; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + if (!func(stream, field, *(const void* const*)p)) + return false; + } + else + { + if (!func(stream, field, p)) + return false; + } + p = (const char*)p + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) +{ + pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + if (field->size_offset != 0) + return *(const pb_size_t*)pSize == 0; + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + return false; /* Fixed length array */ + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset != 0) + { + /* Proto2 optional fields inside proto3 submessage */ + return safe_read_bool(pSize) == false; + } + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) + { + do + { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + { + /* Static optional, repeated or oneof field */ + pSize = (const char*)pData + field->size_offset; + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + } + else + { + /* Required field, always present */ + implicit_has = true; + } + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (safe_read_bool(pSize)) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: { + pb_size_t count; + if (field->size_offset != 0) { + count = *(const pb_size_t*)pSize; + } else { + count = field->array_size; + } + if (!encode_array(stream, field, pData, count, func)) + return false; + break; + } + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) + { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); + } + else + { + return encode_field(stream, field, extension->dest); + } +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +#ifdef PB_WITHOUT_64BIT +bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + if (compensation) + { + /* re-set all the compensation bits we can or need */ + size_t bits = compensation > 7 ? 7 : compensation; + value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */ + compensation -= bits; + } + i++; + } + buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} +#endif + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) + { + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); + } + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + uint32_t value = safe_read_bool(src) ? 1 : 0; + PB_UNUSED(field); + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + +#ifdef PB_WITHOUT_64BIT + if (value < 0) + return pb_encode_negative_varint(stream, (pb_uint64_t)value); + else +#endif + return pb_encode_varint(stream, (pb_uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)src; + + if (src == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char*)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t*)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); +} + diff --git a/MyExperiences copy/Pods/nanopb/pb_encode.h b/MyExperiences copy/Pods/nanopb/pb_encode.h new file mode 100644 index 00000000..8bf78dd5 --- /dev/null +++ b/MyExperiences copy/Pods/nanopb/pb_encode.h @@ -0,0 +1,170 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif